diff --git a/TwlBkpCheck/Windows/FalsifyTwlBackup/Program.cs b/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.cs
similarity index 93%
rename from TwlBkpCheck/Windows/FalsifyTwlBackup/Program.cs
rename to TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.cs
index 5ba6a74..f20ac5d 100644
--- a/TwlBkpCheck/Windows/FalsifyTwlBackup/Program.cs
+++ b/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.cs
@@ -49,6 +49,7 @@ namespace FalsifyTwlBackup
private const int CAT300 = 3;
private const int CAT400 = 4;
private const int CAT500 = 5;
+ private const int VERIFY = 9; // TORIAEZU : 上記が Mode == Pattern なのが引っかかる・・・
// 各カテゴリでの最大番号
private const int MAX_OF_CAT100 = 118;
@@ -90,8 +91,9 @@ namespace FalsifyTwlBackup
Console.WriteLine(" -all (default) : output all falsifying pattern");
Console.WriteLine(" -cat CAT_NUM : output all pattern of CAT_NUM category");
Console.WriteLine(" ex) -cat 100 -> falsifying 100,101,102....");
- Console.WriteLine(" -each PAT_NUM : output PAT_NUM pattern ");
+ Console.WriteLine(" -each PAT_NUM : output PAT_NUM pattern");
Console.WriteLine(" ex) -each 204 -> falsifying 204 only");
+ Console.WriteLine(" -verify : verify backup file");
Environment.Exit(-1);
}
@@ -178,7 +180,14 @@ namespace FalsifyTwlBackup
return Convert.ToInt16(args[4]);
}
}
+
+ // -verify
+ else if (args[3].ToUpper().TrimStart('-') == "VERIFY")
+ {
+ return VERIFY;
+ }
}
+
// それ以外
return ALL;
}
@@ -257,19 +266,31 @@ namespace FalsifyTwlBackup
switch (index)
{
case INDEX_BANNER:
- hash.CopyTo(signature.digest.banner, 0);
- break;
+ hash.CopyTo(signature.digest.banner, 0);
+ break;
case INDEX_HEADER:
- hash.CopyTo(signature.digest.header, 0);
- break;
+ hash.CopyTo(signature.digest.header, 0);
+ break;
case INDEX_TMD:
+ hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0);
+ break;
+
+ // TODO : マルチコンテンツ対応
case INDEX_CONTENT:
+ hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.CONTENT], 0);
+ break;
+
case INDEX_PUBLIC_SAVE:
+ hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0);
+ break;
+
case INDEX_SUB_BANNER:
- hash.CopyTo(signature.digest.section[index - (INDEX_SIGNATURE + 1)], 0);
- break;
+ hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0);
+ break;
+
+ // TODO : Private Save 追加
default:
Debug.Assert(false);
@@ -286,38 +307,6 @@ namespace FalsifyTwlBackup
/// 連結後のbyte列
static byte[] MergeByteArray(byte[] front, byte[] rear)
{
- /* 私のコード(色々アレだよ;;)
- byte[] merged = new byte[front.Length + rear.Length];
- for (int i = 0; i < (front.Length + rear.Length); i++)
- {
- if (i < front.Length)
- {
- merged[i] = front[i];
- }
- else
- {
- merged[i] = rear[i - front.Length];
- }
- }
- */
-
- /* 田中さん案1(中にifは使わないほうがいいよ)
- for (int i = 0; i < front.Length; i++)
- {
- merged[i] = front[i];
- }
- for (int i = 0; i < rear.Length; i++)
- {
- merged[i + front.Length] = rear[i];
- }
- */
-
- /* 田中さん案2(ライブラリを使うとコピーしてるのも分かりやすいよ^^)
- Array.Copy(front, 0, merged, 0, front.Length);
- Array.Copy(rear, 0, merged, front.Length, rear.Length);
- */
-
- // 田中さん案3(結局1行で出来ちゃったよ;;)
return front.Concat(rear).ToArray();
}
@@ -395,7 +384,7 @@ namespace FalsifyTwlBackup
///
- /// 各ブロックを暗号化した後、1つのbute列に結合します。
+ /// 各ブロックを暗号化した後、1つの byte 列に結合します。
///
/// 暗号化するデータ
/// バックアップデータに関するインスタンス
@@ -662,7 +651,10 @@ namespace FalsifyTwlBackup
break;
case 211:
- header.contentId++;
+ for (int i = 0; i < header.contentId.Length; i++)
+ {
+ header.contentId[i]++;
+ }
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break;
@@ -1072,7 +1064,6 @@ namespace FalsifyTwlBackup
Properties prop = new Properties(); // インスタンスの作成
byte[] twlBackupData = File.ReadAllBytes(twlBackupName); // バックアップデータの読み込み
- prop.SetOutputFolderPath(twlBackupName); // 出力フォルダを作成
// 鍵データの読み込み
string[] keyString = File.ReadAllLines(keyName);
@@ -1092,14 +1083,25 @@ namespace FalsifyTwlBackup
// ファイル名の出力 + 鍵データの dump
Console.WriteLine("Twl Backup File : {0}", twlBackupName);
- Console.Write("Block Key File : {0}, ", keyName);
- dumpArray("", prop.keyData);
- Console.Write("MAC Key Data : {0}, ", macKeyData);
- dumpArray("", prop.macKeyData);
+ Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData));
+ Console.WriteLine("MAC Key File : {0} ({1})", macKeyData, dumpArray(prop.macKeyData));
+
+ // TORIAEZU : ひとまず VERIFY だったら検証して終了
+ if (falsifyingType == VERIFY)
+ {
+ if (Utility.Verify(twlBackupData, prop.keyData, prop.macKeyData))
+ {
+ Console.WriteLine("{0} は検証に成功しました。", twlBackupName);
+ }
+ Environment.Exit(0);
+ }
// バックアップデータを復号化
prop.decryptedBlocks = Utility.DecryptBackupData(twlBackupData, prop.keyData);
+ // 出力フォルダを作成
+ prop.SetOutputFolderPath(twlBackupName);
+
//==========================================
// 改ざん&ファイル出力
Console.WriteLine("Start ------------");
@@ -1111,14 +1113,14 @@ namespace FalsifyTwlBackup
}
// byte 配列の 16 進表示
- static void dumpArray(String msg, byte[] array)
+ static string dumpArray(byte[] array)
{
- Console.Write(msg);
+ string str = "";
foreach (byte b in array)
{
- Console.Write(String.Format("{0,0:X2} ", b));
+ str += String.Format("{0,0:X2} ", b);
}
- Console.WriteLine();
+ return str.TrimEnd();
}
}
diff --git a/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.csproj b/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.csproj
index 9b0d4b3..c58ae29 100644
--- a/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.csproj
+++ b/TwlBkpCheck/Windows/FalsifyTwlBackup/FalsifyTwlBackup.csproj
@@ -43,7 +43,7 @@
-
+
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/ExtBinaryReader.cs b/TwlBkpCheck/Windows/TWLBackupBlock/ExtBinaryReader.cs
index 9ec8b25..f182b25 100644
--- a/TwlBkpCheck/Windows/TWLBackupBlock/ExtBinaryReader.cs
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/ExtBinaryReader.cs
@@ -123,6 +123,18 @@ namespace TwlBackupBlock
br.Read(buffer, 0, buffer.Length);
}
+ ///
+ /// 現在のストリームから指定した配列に2バイト符号なし整数を読み取り、ストリームの現在位置を指定した配列のバイト数だけ進めます。
+ ///
+ /// データを読み取るバッファ
+ public void Read(UInt16[] buffer)
+ {
+ for (int i = 0; i < buffer.Length; i++)
+ {
+ Read(ref buffer[i]);
+ }
+ }
+
///
/// 現在のストリームから指定した配列に4バイト符号なし整数を読み取り、ストリームの現在位置を指定した配列のバイト数だけ進めます。
///
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/HeaderBody.cs b/TwlBkpCheck/Windows/TWLBackupBlock/HeaderBody.cs
index a84680e..2c9d556 100644
--- a/TwlBkpCheck/Windows/TWLBackupBlock/HeaderBody.cs
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/HeaderBody.cs
@@ -9,13 +9,14 @@ namespace TwlBackupBlock
///
public class HeaderBody : AbstractBody
{
- public const int HEADER_SIZE = 160;
+ public const int HEADER_SIZE = 240;
public const int UNIQUE_ID_SIZE = 32;
public const int HARDWARE_ID_SIZE = 16;
- public const int NUM_OF_SECTION = 4;
+ public const int MAX_CONTENTS = 8;
+ public const int NUM_OF_SECTION = 11;
public const int TMD_RESERVED_SIZE = 62;
- public const int RESERVED_SIZE = 4;
+ public const int RESERVED_SIZE = 13;
public UInt32 signature;
public UInt16 companyCode;
@@ -25,9 +26,10 @@ namespace TwlBackupBlock
public UInt64 titleId;
public Int64 requiredSize;
public readonly UInt32[] fileSizes;
- public UInt32 contentId;
+ public readonly UInt32[] contentId;
+ public readonly UInt16[] contentIndex;
public readonly TmdReserved tmdReserved;
- public UInt16 contentIndex;
+ public Byte headerVersion;
public readonly Byte[] reserved;
public HeaderBody(byte[] data)
@@ -45,6 +47,8 @@ namespace TwlBackupBlock
uniqueId = new Byte[UNIQUE_ID_SIZE];
hardwareId = new Byte[HARDWARE_ID_SIZE];
fileSizes = new UInt32[NUM_OF_SECTION];
+ contentId = new UInt32[MAX_CONTENTS];
+ contentIndex = new UInt16[MAX_CONTENTS];
tmdReserved = new TmdReserved();
reserved = new Byte[RESERVED_SIZE];
@@ -130,9 +134,16 @@ namespace TwlBackupBlock
{
bw.Write(e);
}
- bw.Write(contentId);
+ foreach (UInt32 e in contentId)
+ {
+ bw.Write(e);
+ }
+ foreach (UInt16 e in contentIndex)
+ {
+ bw.Write(e);
+ }
bw.Write(tmdReserved.GetBytes());
- bw.Write(contentIndex);
+ bw.Write(headerVersion);
bw.Write(reserved);
Debug.Assert(ms.Position == HEADER_SIZE);
@@ -164,13 +175,14 @@ namespace TwlBackupBlock
br.Read(ref titleId);
br.Read(ref requiredSize);
br.Read(fileSizes);
- br.Read(ref contentId);
+ br.Read(contentId);
+ br.Read(contentIndex);
{
byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
br.Read(tmdReservedBytes);
tmdReserved.SetBytes(tmdReservedBytes);
}
- br.Read(ref contentIndex);
+ br.Read(ref headerVersion);
br.Read(reserved);
Debug.Assert(ms.Position == HEADER_SIZE);
@@ -182,79 +194,4 @@ namespace TwlBackupBlock
return new HeaderBody(GetBytes());
}
}
-
- ///
- /// ヘッダブロック中のTMDReserved。
- ///
- public class TmdReserved
- {
- private const int TMD_RESERVED_SIZE = 62;
-
- public const int RESERVED8_SIZE = 3;
- public const int PARENTAL_CONTROL_SIZE = 16;
- public const int RESERVED_SIZE = 30;
-
- public UInt32 publicSaveSize;
- public UInt32 privateSaveSize;
- public UInt32 reserved32;
- public Byte flags;
- public readonly Byte[] reserved8;
- public readonly Byte[] parentalControl;
- public readonly Byte[] reserved;
-
- public TmdReserved()
- {
- reserved8 = new Byte[RESERVED8_SIZE];
- parentalControl = new Byte[PARENTAL_CONTROL_SIZE];
- reserved = new Byte[RESERVED_SIZE];
- }
-
- public byte[] GetBytes()
- {
- byte[] bytes = new byte[TMD_RESERVED_SIZE];
-
- using (var ms = new MemoryStream(bytes))
- using (var bw = new BinaryWriter(ms))
- {
- bw.Write(publicSaveSize);
- bw.Write(privateSaveSize);
- bw.Write(reserved32);
- bw.Write(flags);
- bw.Write(reserved8);
- bw.Write(parentalControl);
- bw.Write(reserved);
-
- Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
- }
-
- return bytes;
- }
-
- public void SetBytes(byte[] bytes)
- {
- if (bytes == null)
- {
- throw new ArgumentNullException("bytes");
- }
- if (bytes.Length != TMD_RESERVED_SIZE)
- {
- string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", TMD_RESERVED_SIZE, bytes.Length);
- throw new ArgumentException("bytes", message);
- }
-
- using (var ms = new MemoryStream(bytes))
- using (var br = new ExtBinaryReader(ms))
- {
- br.Read(ref publicSaveSize);
- br.Read(ref privateSaveSize);
- br.Read(ref reserved32);
- br.Read(ref flags);
- br.Read(reserved8);
- br.Read(parentalControl);
- br.Read(reserved);
-
- Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
- }
- }
- }
}
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/LegacyHeaderBody.cs b/TwlBkpCheck/Windows/TWLBackupBlock/LegacyHeaderBody.cs
new file mode 100644
index 0000000..6c7f179
--- /dev/null
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/LegacyHeaderBody.cs
@@ -0,0 +1,185 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace TwlBackupBlock
+{
+ ///
+ /// ヘッダブロックのデータ本体。
+ ///
+ public class LegacyHeaderBody : AbstractBody
+ {
+ public const int HEADER_SIZE = 160;
+
+ public const int UNIQUE_ID_SIZE = 32;
+ public const int HARDWARE_ID_SIZE = 16;
+ public const int NUM_OF_SECTION = 4;
+ public const int TMD_RESERVED_SIZE = 62;
+ public const int RESERVED_SIZE = 4;
+
+ public UInt32 signature;
+ public UInt16 companyCode;
+ public UInt16 version;
+ public readonly Byte[] uniqueId;
+ public readonly Byte[] hardwareId;
+ public UInt64 titleId;
+ public Int64 requiredSize;
+ public readonly UInt32[] fileSizes;
+ public UInt32 contentId;
+ public readonly TmdReserved tmdReserved;
+ public UInt16 contentIndex;
+ public readonly Byte[] reserved;
+
+ public LegacyHeaderBody(byte[] data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+ if (data.Length != HEADER_SIZE)
+ {
+ string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", HEADER_SIZE, data.Length);
+ throw new ArgumentException("data", message);
+ }
+
+ uniqueId = new Byte[UNIQUE_ID_SIZE];
+ hardwareId = new Byte[HARDWARE_ID_SIZE];
+ fileSizes = new UInt32[NUM_OF_SECTION];
+ tmdReserved = new TmdReserved();
+ reserved = new Byte[RESERVED_SIZE];
+
+ SetBytes(data);
+ }
+
+ public override byte this[int index]
+ {
+ get
+ {
+ if (index < 0 || index >= HEADER_SIZE)
+ {
+ throw new ArgumentException("index");
+ }
+ return ReadByte(index);
+ }
+ set
+ {
+ if (index < 0 || index >= HEADER_SIZE)
+ {
+ throw new ArgumentException("index");
+ }
+ WriteByte(index, value);
+ }
+ }
+
+ public override int Length
+ {
+ get
+ {
+ return HEADER_SIZE;
+ }
+ }
+
+ ///
+ /// 指定したバイトを取得します。
+ ///
+ /// 取得したいバイトのインデックス。
+ /// で指定したバイト
+ public byte ReadByte(int index)
+ {
+ if (index < 0 || index >= HEADER_SIZE)
+ {
+ throw new ArgumentException("index");
+ }
+ // TODO 処理が遅ければ効率化
+ byte[] bytes = GetBytes();
+ return bytes[index];
+ }
+
+ ///
+ /// 指定したバイトを書き換えます。
+ ///
+ /// 書き換えたいバイトのインデックス。
+ /// 上書きに使うバイト。
+ public void WriteByte(int index, byte b)
+ {
+ if (index < 0 || index >= HEADER_SIZE)
+ {
+ throw new ArgumentException("index");
+ }
+ // TODO 処理が遅ければ効率化
+ byte[] bytes = GetBytes();
+ bytes[index] = b;
+ SetBytes(bytes);
+ }
+
+ public override byte[] GetBytes()
+ {
+ byte[] bytes = new byte[HEADER_SIZE];
+
+ using (var ms = new MemoryStream(bytes))
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(signature);
+ bw.Write(companyCode);
+ bw.Write(version);
+ bw.Write(uniqueId);
+ bw.Write(hardwareId);
+ bw.Write(titleId);
+ bw.Write(requiredSize);
+ foreach (UInt32 e in fileSizes)
+ {
+ bw.Write(e);
+ }
+ bw.Write(contentId);
+ bw.Write(tmdReserved.GetBytes());
+ bw.Write(contentIndex);
+ bw.Write(reserved);
+
+ Debug.Assert(ms.Position == HEADER_SIZE);
+ }
+
+ return bytes;
+ }
+
+ public override void SetBytes(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes");
+ }
+ if (bytes.Length != HEADER_SIZE)
+ {
+ string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", HEADER_SIZE, bytes.Length);
+ throw new ArgumentException("bytes", message);
+ }
+
+ using (var ms = new MemoryStream(bytes))
+ using (var br = new ExtBinaryReader(ms))
+ {
+ br.Read(ref signature);
+ br.Read(ref companyCode);
+ br.Read(ref version);
+ br.Read(uniqueId);
+ br.Read(hardwareId);
+ br.Read(ref titleId);
+ br.Read(ref requiredSize);
+ br.Read(fileSizes);
+ br.Read(ref contentId);
+ {
+ byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
+ br.Read(tmdReservedBytes);
+ tmdReserved.SetBytes(tmdReservedBytes);
+ }
+ br.Read(ref contentIndex);
+ br.Read(reserved);
+
+ Debug.Assert(ms.Position == HEADER_SIZE);
+ }
+ }
+
+ public override object Clone()
+ {
+ return new HeaderBody(GetBytes());
+ }
+ }
+}
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/SignatureBody.cs b/TwlBkpCheck/Windows/TWLBackupBlock/SignatureBody.cs
index 69b6546..5a27d0d 100644
--- a/TwlBkpCheck/Windows/TWLBackupBlock/SignatureBody.cs
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/SignatureBody.cs
@@ -10,7 +10,8 @@ namespace TwlBackupBlock
public class TwlBackupHashSet
{
public const int HASH_SIZE = 32;
- public const int NUM_OF_SECTION = 4;
+ public const int NUM_OF_SECTION = 11;
+ public const int NUM_OF_LEGACY_SECTION = 4;
public readonly byte[] banner;
public readonly byte[] header;
@@ -19,11 +20,12 @@ namespace TwlBackupBlock
///
/// コンストラクタ。
///
- public TwlBackupHashSet()
+ public TwlBackupHashSet(bool isLegacy = false)
{
banner = new byte[HASH_SIZE];
header = new byte[HASH_SIZE];
- section = new byte[NUM_OF_SECTION][];
+ section = isLegacy ?
+ new byte[NUM_OF_LEGACY_SECTION][] : new byte[NUM_OF_SECTION][];
for (int i = 0; i < section.Length; i++)
{
section[i] = new byte[HASH_SIZE];
@@ -35,7 +37,8 @@ namespace TwlBackupBlock
///
public class SignatureBody : AbstractBody
{
- public const int SIGNATURE_SIZE = 1024;
+ public const int SIGNATURE_SIZE = 1248;
+ public const int LEGACY_SIGNATURE_SIZE = 1024;
public const int ECC_SIGN_SIZE = 60;
public const int ECC_CERT_SIZE = 384;
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/TmdReserved.cs b/TwlBkpCheck/Windows/TWLBackupBlock/TmdReserved.cs
new file mode 100644
index 0000000..257d04c
--- /dev/null
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/TmdReserved.cs
@@ -0,0 +1,82 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace TwlBackupBlock
+{
+ ///
+ /// ヘッダブロック中のTMDReserved。
+ /// Normal, Legacy 共に共通。
+ ///
+ public class TmdReserved
+ {
+ private const int TMD_RESERVED_SIZE = 62;
+
+ public const int RESERVED8_SIZE = 3;
+ public const int PARENTAL_CONTROL_SIZE = 16;
+ public const int RESERVED_SIZE = 30;
+
+ public UInt32 publicSaveSize;
+ public UInt32 privateSaveSize;
+ public UInt32 reserved32;
+ public Byte flags;
+ public readonly Byte[] reserved8;
+ public readonly Byte[] parentalControl;
+ public readonly Byte[] reserved;
+
+ public TmdReserved()
+ {
+ reserved8 = new Byte[RESERVED8_SIZE];
+ parentalControl = new Byte[PARENTAL_CONTROL_SIZE];
+ reserved = new Byte[RESERVED_SIZE];
+ }
+
+ public byte[] GetBytes()
+ {
+ byte[] bytes = new byte[TMD_RESERVED_SIZE];
+
+ using (var ms = new MemoryStream(bytes))
+ using (var bw = new BinaryWriter(ms))
+ {
+ bw.Write(publicSaveSize);
+ bw.Write(privateSaveSize);
+ bw.Write(reserved32);
+ bw.Write(flags);
+ bw.Write(reserved8);
+ bw.Write(parentalControl);
+ bw.Write(reserved);
+
+ Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
+ }
+
+ return bytes;
+ }
+
+ public void SetBytes(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes");
+ }
+ if (bytes.Length != TMD_RESERVED_SIZE)
+ {
+ string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", TMD_RESERVED_SIZE, bytes.Length);
+ throw new ArgumentException("bytes", message);
+ }
+
+ using (var ms = new MemoryStream(bytes))
+ using (var br = new ExtBinaryReader(ms))
+ {
+ br.Read(ref publicSaveSize);
+ br.Read(ref privateSaveSize);
+ br.Read(ref reserved32);
+ br.Read(ref flags);
+ br.Read(reserved8);
+ br.Read(parentalControl);
+ br.Read(reserved);
+
+ Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
+ }
+ }
+ }
+}
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/TwlBackupBlock.csproj b/TwlBkpCheck/Windows/TWLBackupBlock/TwlBackupBlock.csproj
index e41b545..f803879 100644
--- a/TwlBkpCheck/Windows/TWLBackupBlock/TwlBackupBlock.csproj
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/TwlBackupBlock.csproj
@@ -58,6 +58,7 @@
+
True
True
@@ -68,6 +69,7 @@
True
Settings.settings
+
diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs b/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs
index d12c4b3..40d1bc3 100644
--- a/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs
+++ b/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs
@@ -13,6 +13,16 @@ namespace TwlBackupBlock
///
public class Utility
{
+ public const int MAX_CONTENTS = 8;
+ public enum SectionIndex
+ {
+ TMD,
+ CONTENT,
+ PUBLIC_SAVE = CONTENT + MAX_CONTENTS,
+ SUB_BANNER,
+ PRIVATE_SAVE
+ };
+
private const int KEY_SIZE = 16;
private const int ROUND_SCALE = 16;
@@ -21,8 +31,10 @@ namespace TwlBackupBlock
private const int AES_SIGN_HEADER_SIZE = 32;
private const int BANNER_SIZE = 16 * 1024;
- private const int HEADER_SIZE = 160;
- private const int SIGNATURE_SIZE = 1024;
+ private const int HEADER_SIZE = 240;
+ private const int SIGNATURE_SIZE = 1248;
+ private const int LEGACY_HEADER_SIZE = 160;
+ private const int LEGACY_SIGNATURE_SIZE = 1024;
private const int ENCRYPT_BANNER_SIZE = BANNER_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_HEADER_SIZE = HEADER_SIZE + AES_SIGN_HEADER_SIZE;
@@ -74,14 +86,16 @@ namespace TwlBackupBlock
blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv));
- int TMD_SIZE = (int)headerBody.fileSizes[0];
- int CONTENT_SIZE = (int)headerBody.fileSizes[1];
- int SAVE_DATA_SIZE = (int)headerBody.fileSizes[2];
- int SUB_BANNER_SIZE = (int)headerBody.fileSizes[3];
+ // TORIAEZU
+ // TODO : 複数コンテンツ対応
+ int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
+ int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
+ int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
+ int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
blocks.tmd.body = new Body(DecryptBlock(br, TMD_SIZE, key, out blocks.tmd.mac, out blocks.tmd.iv));
blocks.content.body = new Body(DecryptBlock(br, CONTENT_SIZE, key, out blocks.content.mac, out blocks.content.iv));
- blocks.saveData.body = new Body(DecryptBlock(br, SAVE_DATA_SIZE, key, out blocks.saveData.mac, out blocks.saveData.iv));
+ blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, key, out blocks.saveData.mac, out blocks.saveData.iv));
blocks.subBanner.body = new Body(DecryptBlock(br, SUB_BANNER_SIZE, key, out blocks.subBanner.mac, out blocks.subBanner.iv));
Debug.Assert(ms.Position == data.Length);
@@ -386,13 +400,14 @@ namespace TwlBackupBlock
return false;
}
- int TMD_SIZE = (int)headerBody.fileSizes[0];
- int CONTENT_SIZE = (int)headerBody.fileSizes[1];
- int SAVE_DATA_SIZE = (int)headerBody.fileSizes[2];
- int SUB_BANNER_SIZE = (int)headerBody.fileSizes[3];
+ // TODO : 複数コンテンツ対応
+ int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
+ int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
+ int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
+ int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) + RoundUp(CONTENT_SIZE, ROUND_SCALE) +
- RoundUp(SAVE_DATA_SIZE, ROUND_SCALE) + RoundUp(SUB_BANNER_SIZE, ROUND_SCALE) +
+ RoundUp(PUBLIC_SAVE_SIZE, ROUND_SCALE) + RoundUp(SUB_BANNER_SIZE, ROUND_SCALE) +
AES_SIGN_HEADER_SIZE * 4;
if (data.Length - ms.Position != restSize)
{
@@ -405,7 +420,7 @@ namespace TwlBackupBlock
Console.WriteLine("TMDブロックのMACが一致しません");
return false;
}
- if (!CheckHash(blocks.tmd, signatureBody.digest.section[0]))
+ if (!CheckHash(blocks.tmd, signatureBody.digest.section[(int)SectionIndex.TMD]))
{
Console.WriteLine("TMDブロックのハッシュが一致しません");
return false;
@@ -416,18 +431,18 @@ namespace TwlBackupBlock
Console.WriteLine("コンテンツブロックのMACが一致しません");
return false;
}
- if (!CheckHash(blocks.content, signatureBody.digest.section[1]))
+ if (!CheckHash(blocks.content, signatureBody.digest.section[(int)SectionIndex.CONTENT]))
{
Console.WriteLine("コンテンツブロックのハッシュが一致しません");
return false;
}
- blocks.saveData.body = new Body(DecryptBlock(br, SAVE_DATA_SIZE, aesCbcKey, out blocks.saveData.mac, out blocks.saveData.iv));
+ blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, aesCbcKey, out blocks.saveData.mac, out blocks.saveData.iv));
if (!CheckMac(blocks.saveData, aesCmacKey, blocks.saveData.mac))
{
Console.WriteLine("publicセーブデータブロックのMACが一致しません");
return false;
}
- if (!CheckHash(blocks.saveData, signatureBody.digest.section[2]))
+ if (!CheckHash(blocks.saveData, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE]))
{
Console.WriteLine("publicセーブデータブロックのハッシュが一致しません");
return false;
@@ -438,7 +453,7 @@ namespace TwlBackupBlock
Console.WriteLine("サブバナーブロックの内容とMACが一致しません");
return false;
}
- if (!CheckHash(blocks.subBanner, signatureBody.digest.section[3]))
+ if (!CheckHash(blocks.subBanner, signatureBody.digest.section[(int)SectionIndex.SUB_BANNER]))
{
Console.WriteLine("サブバナーブロックのハッシュが一致しません");
return false;