Fix AesXtsFileSystem bugs and add the option to specify keys

This commit is contained in:
Alex Barney 2019-02-07 20:32:57 -06:00
parent fb7254684a
commit 2844466bbb
4 changed files with 33 additions and 9 deletions

View file

@ -5,14 +5,16 @@ namespace LibHac.IO
{ {
public class AesXtsDirectory : IDirectory public class AesXtsDirectory : IDirectory
{ {
public IFileSystem ParentFileSystem { get; } IFileSystem IDirectory.ParentFileSystem => ParentFileSystem;
public AesXtsFileSystem ParentFileSystem { get; }
public string FullPath { get; } public string FullPath { get; }
public OpenDirectoryMode Mode { get; } public OpenDirectoryMode Mode { get; }
private IFileSystem BaseFileSystem { get; } private IFileSystem BaseFileSystem { get; }
private IDirectory BaseDirectory { get; } private IDirectory BaseDirectory { get; }
public AesXtsDirectory(IFileSystem parentFs, IDirectory baseDir, OpenDirectoryMode mode) public AesXtsDirectory(AesXtsFileSystem parentFs, IDirectory baseDir, OpenDirectoryMode mode)
{ {
ParentFileSystem = parentFs; ParentFileSystem = parentFs;
BaseDirectory = baseDir; BaseDirectory = baseDir;
@ -66,7 +68,7 @@ namespace LibHac.IO
if (BitConverter.ToUInt32(buffer, 0) != 0x3058414E) return 0; if (BitConverter.ToUInt32(buffer, 0) != 0x3058414E) return 0;
file.Read(buffer, 0x48); file.Read(buffer, 0x48);
return BitConverter.ToInt32(buffer, 0); return BitConverter.ToInt64(buffer, 0);
} }
} }
catch (ArgumentOutOfRangeException) catch (ArgumentOutOfRangeException)

View file

@ -31,10 +31,19 @@ namespace LibHac.IO
throw new ArgumentException("NAX0 key derivation failed."); throw new ArgumentException("NAX0 key derivation failed.");
} }
IStorage encStorage = BaseFile.AsStorage().Slice(HeaderLength, Header.Size); IStorage encStorage = BaseFile.AsStorage().Slice(HeaderLength, Util.AlignUp(Header.Size, 0x10));
BaseStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Header.DecryptedKey1, Header.DecryptedKey2, BlockSize, true), 4, true); BaseStorage = new CachedStorage(new Aes128XtsStorage(encStorage, Header.DecryptedKey1, Header.DecryptedKey2, BlockSize, true), 4, true);
} }
public byte[] GetKey()
{
var key = new byte[0x20];
Array.Copy(Header.DecryptedKey1, 0, key, 0, 0x10);
Array.Copy(Header.DecryptedKey2, 0, key, 0x10, 0x10);
return key;
}
public override int Read(Span<byte> destination, long offset) public override int Read(Span<byte> destination, long offset)
{ {
int toRead = ValidateReadParamsAndGetSize(destination, offset); int toRead = ValidateReadParamsAndGetSize(destination, offset);

View file

@ -37,10 +37,10 @@ namespace LibHac.IO
} }
} }
public AesXtsFileHeader(byte[] key1, byte[] key2, long fileSize, string path, byte[] kekSeed, byte[] verificationKey) public AesXtsFileHeader(byte[] key, long fileSize, string path, byte[] kekSeed, byte[] verificationKey)
{ {
Array.Copy(key1, DecryptedKey1, 0x10); Array.Copy(key, 0, DecryptedKey1, 0, 0x10);
Array.Copy(key2, DecryptedKey2, 0x10); Array.Copy(key, 0x10, DecryptedKey2, 0, 0x10);
Magic = AesXtsFileMagic; Magic = AesXtsFileMagic;
Size = fileSize; Size = fileSize;

View file

@ -33,10 +33,23 @@ namespace LibHac.IO
public void CreateFile(string path, long size, CreateFileOptions options) public void CreateFile(string path, long size, CreateFileOptions options)
{ {
long containerSize = AesXtsFile.HeaderLength + Util.AlignUp(size, 0x16); CreateFile(path, size, options, new byte[0x20]);
}
/// <summary>
/// Creates a new <see cref="AesXtsFile"/> using the provided key.
/// </summary>
/// <param name="path">The full path of the file to create.</param>
/// <param name="size">The initial size of the created file.</param>
/// <param name="options">Flags to control how the file is created.
/// Should usually be <see cref="CreateFileOptions.None"/></param>
/// <param name="key">The 256-bit key containing a 128-bit data key followed by a 128-bit tweak key.</param>
public void CreateFile(string path, long size, CreateFileOptions options, byte[] key)
{
long containerSize = AesXtsFile.HeaderLength + Util.AlignUp(size, 0x10);
BaseFileSystem.CreateFile(path, containerSize, options); BaseFileSystem.CreateFile(path, containerSize, options);
var header = new AesXtsFileHeader(new byte[0x10], new byte[0x10], size, path, KekSource, ValidationKey); var header = new AesXtsFileHeader(key, size, path, KekSource, ValidationKey);
using (IFile baseFile = BaseFileSystem.OpenFile(path, OpenMode.Write)) using (IFile baseFile = BaseFileSystem.OpenFile(path, OpenMode.Write))
{ {