Add Savefile.CommitHeader method

This commit is contained in:
Alex Barney 2018-10-18 18:18:39 -05:00
parent f83a284b96
commit 7a7946a26c
4 changed files with 48 additions and 26 deletions

View file

@ -21,6 +21,14 @@ namespace LibHac
return comp;
}
public static byte[] ComputeSha256(byte[] data, int offset, int count)
{
using (SHA256 sha = SHA256.Create())
{
return sha.ComputeHash(data, offset, count);
}
}
public static void DecryptEcb(byte[] key, byte[] src, int srcIndex, byte[] dest, int destIndex, int length)
{
using (Aes aes = Aes.Create())

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using LibHac.Streams;
namespace LibHac.Save
{
@ -24,13 +25,17 @@ namespace LibHac.Save
public byte[] DuplexMasterA { get; }
public byte[] DuplexMasterB { get; }
public Stream MasterHash { get; }
public Validity SignatureValidity { get; }
public Validity HeaderHashValidity { get; }
public byte[] Data { get; }
public Header(Keyset keyset, BinaryReader reader)
public Header(Keyset keyset, SharedStreamSource streamSource)
{
var reader = new BinaryReader(streamSource.CreateStream());
reader.BaseStream.Position = 0;
Data = reader.ReadBytes(0x4000);
reader.BaseStream.Position = 0;
@ -65,6 +70,8 @@ namespace LibHac.Save
reader.BaseStream.Position = Layout.IvfcMasterHashOffsetB;
MasterHashB = reader.ReadBytes((int)Layout.IvfcMasterHashSize);
MasterHash = streamSource.CreateStream(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);
reader.BaseStream.Position = Layout.DuplexMasterOffsetA;
DuplexMasterA = reader.ReadBytes((int)Layout.DuplexMasterSize);
reader.BaseStream.Position = Layout.DuplexMasterOffsetB;

View file

@ -28,9 +28,7 @@ namespace LibHac.Save
{
SavefileSource = new SharedStreamSource(file);
using (var reader = new BinaryReader(SavefileSource.CreateStream(), Encoding.Default, true))
{
Header = new Header(keyset, reader);
Header = new Header(keyset, SavefileSource);
FsLayout layout = Header.Layout;
DataRemapStorage = new RemapStorage(SavefileSource.CreateStream(layout.FileMapDataOffset, layout.FileMapDataSize),
@ -55,7 +53,6 @@ namespace LibHac.Save
IvfcStreamSource = new SharedStreamSource(IvfcStream);
}
}
private static LayeredDuplexFs InitDuplexStream(RemapStorage baseStorage, Header header)
{
@ -95,7 +92,7 @@ namespace LibHac.Save
initInfo[0] = new IntegrityVerificationInfo
{
Data = new MemoryStream(Header.MasterHashA),
Data = Header.MasterHash,
BlockSize = 0,
Type = IntegrityStreamType.Save
};
@ -132,18 +129,28 @@ namespace LibHac.Save
public bool FileExists(string filename) => SaveFs.FileExists(filename);
public bool SignHeader(Keyset keyset)
public bool CommitHeader(Keyset keyset)
{
SharedStream headerStream = SavefileSource.CreateStream();
var hashData = new byte[0x3d00];
headerStream.Position = 0x300;
headerStream.Read(hashData, 0, hashData.Length);
byte[] hash = Crypto.ComputeSha256(hashData, 0, hashData.Length);
headerStream.Position = 0x108;
headerStream.Write(hash, 0, hash.Length);
if (keyset.SaveMacKey.IsEmpty()) return false;
var data = new byte[0x200];
var cmacData = new byte[0x200];
var cmac = new byte[0x10];
SharedStream headerStream = SavefileSource.CreateStream();
headerStream.Position = 0x100;
headerStream.Read(data, 0, 0x200);
headerStream.Read(cmacData, 0, 0x200);
Crypto.CalculateAesCmac(keyset.SaveMacKey, data, 0, cmac, 0, 0x200);
Crypto.CalculateAesCmac(keyset.SaveMacKey, cmacData, 0, cmac, 0, 0x200);
headerStream.Position = 0;
headerStream.Write(cmac, 0, 0x10);

View file

@ -73,7 +73,7 @@ namespace hactoolnet
if (ctx.Options.SignSave)
{
if (save.SignHeader(ctx.Keyset))
if (save.CommitHeader(ctx.Keyset))
{
ctx.Logger.LogMessage("Successfully signed save file");
}