FalsifyTwlBackup:BkpType Legacy に対応。

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@38 6b0af911-cb57-b745-895f-eec5701120e1
This commit is contained in:
n2460 2011-10-27 11:50:55 +00:00
parent 4978389346
commit 12cf32bf6b
2 changed files with 114 additions and 43 deletions

View File

@ -23,6 +23,10 @@ namespace TwlBackupBlock
// for WithPrivateSave // for WithPrivateSave
public const int RESERVED_SIZE_FOR_WPS = 12; public const int RESERVED_SIZE_FOR_WPS = 12;
// for Legacy
public const int RESERVED_SIZE_FOR_LEGACY = 4;
public const int NUM_OF_SECTION_LEGACY = 4;
public UInt32 signature; public UInt32 signature;
public UInt16 companyCode; public UInt16 companyCode;
public UInt16 version; public UInt16 version;
@ -41,6 +45,10 @@ namespace TwlBackupBlock
public UInt32 privateSaveForWPS; public UInt32 privateSaveForWPS;
public readonly Byte[] reservedForWPS; public readonly Byte[] reservedForWPS;
// for Legacy
public UInt32 contentIdForLegacy;
public UInt16 contentIndexForLegacy;
private BkpType type; private BkpType type;
private int headerSize; private int headerSize;
@ -72,12 +80,19 @@ namespace TwlBackupBlock
uniqueId = new Byte[UNIQUE_ID_SIZE]; uniqueId = new Byte[UNIQUE_ID_SIZE];
hardwareId = new Byte[HARDWARE_ID_SIZE]; hardwareId = new Byte[HARDWARE_ID_SIZE];
fileSizes = new UInt32[NUM_OF_SECTION]; if (type != BkpType.LEGACY)
contentId = new UInt32[MAX_CONTENTS]; {
contentIndex = new UInt16[MAX_CONTENTS]; fileSizes = new UInt32[NUM_OF_SECTION];
contentId = new UInt32[MAX_CONTENTS];
contentIndex = new UInt16[MAX_CONTENTS];
reserved = new Byte[RESERVED_SIZE];
}
else
{
fileSizes = new UInt32[NUM_OF_SECTION_LEGACY];
reserved = new Byte[RESERVED_SIZE_FOR_LEGACY];
}
tmdReserved = new TmdReserved(); tmdReserved = new TmdReserved();
reserved = new Byte[RESERVED_SIZE];
if (type == BkpType.WITH_PRIVATE_SAVE) if (type == BkpType.WITH_PRIVATE_SAVE)
{ {
reservedForWPS = new Byte[RESERVED_SIZE_FOR_WPS]; reservedForWPS = new Byte[RESERVED_SIZE_FOR_WPS];
@ -154,7 +169,6 @@ namespace TwlBackupBlock
using (var ms = new MemoryStream(bytes)) using (var ms = new MemoryStream(bytes))
using (var bw = new BinaryWriter(ms)) using (var bw = new BinaryWriter(ms))
{ {
// TODO : Legacy 対応
bw.Write(signature); bw.Write(signature);
bw.Write(companyCode); bw.Write(companyCode);
bw.Write(version); bw.Write(version);
@ -166,16 +180,33 @@ namespace TwlBackupBlock
{ {
bw.Write(e); bw.Write(e);
} }
foreach (UInt32 e in contentId) if (type != BkpType.LEGACY)
{ {
bw.Write(e); foreach (UInt32 e in contentId)
{
bw.Write(e);
}
} }
foreach (UInt16 e in contentIndex) else
{ {
bw.Write(e); bw.Write(contentIdForLegacy);
}
if (type != BkpType.LEGACY)
{
foreach (UInt16 e in contentIndex)
{
bw.Write(e);
}
} }
bw.Write(tmdReserved.GetBytes()); bw.Write(tmdReserved.GetBytes());
bw.Write(headerVersion); if (type == BkpType.LEGACY)
{
bw.Write(contentIndexForLegacy);
}
if (type != BkpType.LEGACY)
{
bw.Write(headerVersion);
}
bw.Write(reserved); bw.Write(reserved);
if (type == BkpType.WITH_PRIVATE_SAVE) if (type == BkpType.WITH_PRIVATE_SAVE)
{ {
@ -204,7 +235,6 @@ namespace TwlBackupBlock
using (var ms = new MemoryStream(bytes)) using (var ms = new MemoryStream(bytes))
using (var br = new ExtBinaryReader(ms)) using (var br = new ExtBinaryReader(ms))
{ {
// TODO : Legacy 対応
br.Read(ref signature); br.Read(ref signature);
br.Read(ref companyCode); br.Read(ref companyCode);
br.Read(ref version); br.Read(ref version);
@ -213,14 +243,31 @@ namespace TwlBackupBlock
br.Read(ref titleId); br.Read(ref titleId);
br.Read(ref requiredSize); br.Read(ref requiredSize);
br.Read(fileSizes); br.Read(fileSizes);
br.Read(contentId); if (type != BkpType.LEGACY)
br.Read(contentIndex); {
br.Read(contentId);
}
else
{
br.Read(ref contentIdForLegacy);
}
if (type != BkpType.LEGACY)
{
br.Read(contentIndex);
}
{ {
byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE]; byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
br.Read(tmdReservedBytes); br.Read(tmdReservedBytes);
tmdReserved.SetBytes(tmdReservedBytes); tmdReserved.SetBytes(tmdReservedBytes);
} }
br.Read(ref headerVersion); if (type == BkpType.LEGACY)
{
br.Read(ref contentIndexForLegacy);
}
if (type != BkpType.LEGACY)
{
br.Read(ref headerVersion);
}
br.Read(reserved); br.Read(reserved);
if (type == BkpType.WITH_PRIVATE_SAVE) if (type == BkpType.WITH_PRIVATE_SAVE)
{ {

View File

@ -23,6 +23,17 @@ namespace TwlBackupBlock
PRIVATE_SAVE PRIVATE_SAVE
}; };
// いまいち・・・
public const int MAX_CONTENTS_LEGACY = 1;
public enum SectionIndexLegacy
{
TMD,
CONTENT,
PUBLIC_SAVE = CONTENT + MAX_CONTENTS_LEGACY,
SUB_BANNER,
PRIVATE_SAVE
};
private const int KEY_SIZE = 16; private const int KEY_SIZE = 16;
private const int ROUND_SCALE = 16; private const int ROUND_SCALE = 16;
@ -41,8 +52,10 @@ namespace TwlBackupBlock
private const int ENCRYPT_BANNER_SIZE = BANNER_SIZE + AES_SIGN_HEADER_SIZE; private const int ENCRYPT_BANNER_SIZE = BANNER_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_HEADER_SIZE = HEADER_SIZE + AES_SIGN_HEADER_SIZE; private const int ENCRYPT_HEADER_SIZE = HEADER_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_EX_HEADER_SIZE = EX_HEADER_SIZE + AES_SIGN_HEADER_SIZE; private const int ENCRYPT_EX_HEADER_SIZE = EX_HEADER_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_LEGACY_HEADER_SIZE = LEGACY_HEADER_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_SIGNATURE_SIZE = SIGNATURE_SIZE + AES_SIGN_HEADER_SIZE; private const int ENCRYPT_SIGNATURE_SIZE = SIGNATURE_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_EX_SIGNATURE_SIZE = EX_SIGNATURE_SIZE + AES_SIGN_HEADER_SIZE; private const int ENCRYPT_EX_SIGNATURE_SIZE = EX_SIGNATURE_SIZE + AES_SIGN_HEADER_SIZE;
private const int ENCRYPT_LEGACY_SIGNATURE_SIZE = LEGACY_SIGNATURE_SIZE + AES_SIGN_HEADER_SIZE;
/// <summary> /// <summary>
/// バックアップデータをブロックに分割して復号化をおこないます。 /// バックアップデータをブロックに分割して復号化をおこないます。
@ -53,17 +66,13 @@ namespace TwlBackupBlock
/// <returns>分割、復号化されたブロック。</returns> /// <returns>分割、復号化されたブロック。</returns>
public static Blocks DecryptBackupData(byte[] data, byte[] key, BkpType type) public static Blocks DecryptBackupData(byte[] data, byte[] key, BkpType type)
{ {
// TODO : Legacy 対応
if (type == BkpType.LEGACY)
{
Console.WriteLine("Legacy には未対応です。");
return null;
}
int headerSize = 0; int headerSize = 0;
int signatureSize = 0; int signatureSize = 0;
int encryptHeaderSize = 0; int encryptHeaderSize = 0;
int encryptSignatureSize = 0; int encryptSignatureSize = 0;
int contentsNum = MAX_CONTENTS;
int indexPublicSave = (int)SectionIndexLegacy.PUBLIC_SAVE;
int indexSubBanner = (int)SectionIndexLegacy.SUB_BANNER;
switch (type) switch (type)
{ {
@ -80,6 +89,16 @@ namespace TwlBackupBlock
encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE; encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE;
encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE; encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE;
break; break;
case BkpType.LEGACY:
headerSize = LEGACY_HEADER_SIZE;
signatureSize = LEGACY_SIGNATURE_SIZE;
encryptHeaderSize = ENCRYPT_LEGACY_HEADER_SIZE;
encryptSignatureSize = ENCRYPT_LEGACY_SIGNATURE_SIZE;
contentsNum = MAX_CONTENTS_LEGACY;
indexPublicSave = (int)SectionIndexLegacy.PUBLIC_SAVE;
indexSubBanner = (int)SectionIndexLegacy.SUB_BANNER;
break;
} }
if (data == null) if (data == null)
@ -122,15 +141,14 @@ namespace TwlBackupBlock
blocks.signature.body = new SignatureBody( blocks.signature.body = new SignatureBody(
DecryptBlock(br, signatureSize, key, out blocks.signature.mac, out blocks.signature.iv), type); DecryptBlock(br, signatureSize, key, out blocks.signature.mac, out blocks.signature.iv), type);
// TODO : Legacy 対応
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD]; int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
int[] CONTENT_SIZE = new int[MAX_CONTENTS]; int[] CONTENT_SIZE = new int[contentsNum];
for (int i = 0; i < MAX_CONTENTS; i++) for (int i = 0; i < contentsNum; i++)
{ {
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i]; CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
} }
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE]; int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[indexPublicSave];
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; int SUB_BANNER_SIZE = (int)headerBody.fileSizes[indexSubBanner];
int PRIVATE_SAVE_SIZE = 0; int PRIVATE_SAVE_SIZE = 0;
if (type == BkpType.WITH_PRIVATE_SAVE) if (type == BkpType.WITH_PRIVATE_SAVE)
{ {
@ -138,7 +156,7 @@ namespace TwlBackupBlock
} }
blocks.tmd.body = new Body(DecryptBlock(br, TMD_SIZE, key, out blocks.tmd.mac, out blocks.tmd.iv)); blocks.tmd.body = new Body(DecryptBlock(br, TMD_SIZE, key, out blocks.tmd.mac, out blocks.tmd.iv));
for (int i = 0; i < MAX_CONTENTS; i++) for (int i = 0; i < contentsNum; i++)
{ {
if (CONTENT_SIZE[i] > 0) if (CONTENT_SIZE[i] > 0)
{ {
@ -393,17 +411,13 @@ namespace TwlBackupBlock
/// <returns>検証に成功した場合はtrue。それ以外の場合はfalse。</returns> /// <returns>検証に成功した場合はtrue。それ以外の場合はfalse。</returns>
public static bool Verify(byte[] data, byte[] aesCbcKey, byte[] aesCmacKey, BkpType type) public static bool Verify(byte[] data, byte[] aesCbcKey, byte[] aesCmacKey, BkpType type)
{ {
// TODO : Legacy 対応
if (type == BkpType.LEGACY)
{
Console.WriteLine("Legacy には未対応です。");
return false;
}
int headerSize = 0; int headerSize = 0;
int signatureSize = 0; int signatureSize = 0;
int encryptHeaderSize = 0; int encryptHeaderSize = 0;
int encryptSignatureSize = 0; int encryptSignatureSize = 0;
int contentsNum = MAX_CONTENTS;
int indexPublicSave = (int)SectionIndex.PUBLIC_SAVE;
int indexSubBanner = (int)SectionIndex.SUB_BANNER;
switch (type) switch (type)
{ {
@ -420,6 +434,16 @@ namespace TwlBackupBlock
encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE; encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE;
encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE; encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE;
break; break;
case BkpType.LEGACY:
headerSize = LEGACY_HEADER_SIZE;
signatureSize = LEGACY_SIGNATURE_SIZE;
encryptHeaderSize = ENCRYPT_LEGACY_HEADER_SIZE;
encryptSignatureSize = ENCRYPT_LEGACY_SIGNATURE_SIZE;
contentsNum = MAX_CONTENTS_LEGACY;
indexPublicSave = (int)SectionIndexLegacy.PUBLIC_SAVE;
indexSubBanner = (int)SectionIndexLegacy.SUB_BANNER;
break;
} }
if (data == null) if (data == null)
@ -492,13 +516,13 @@ namespace TwlBackupBlock
// TODO : Legacy 対応 // TODO : Legacy 対応
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD]; int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
int[] CONTENT_SIZE = new int[MAX_CONTENTS]; int[] CONTENT_SIZE = new int[contentsNum];
for (int i = 0; i < MAX_CONTENTS; i++) for (int i = 0; i < contentsNum; i++)
{ {
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i]; CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
} }
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE]; int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[indexPublicSave];
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; int SUB_BANNER_SIZE = (int)headerBody.fileSizes[indexSubBanner];
int PRIVATE_SAVE_SIZE = 0; int PRIVATE_SAVE_SIZE = 0;
if (type == BkpType.WITH_PRIVATE_SAVE) if (type == BkpType.WITH_PRIVATE_SAVE)
{ {
@ -508,7 +532,7 @@ namespace TwlBackupBlock
int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) + int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) +
RoundUp(PUBLIC_SAVE_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 * 3; AES_SIGN_HEADER_SIZE * 3;
for (int i = 0; i < MAX_CONTENTS; i++) for (int i = 0; i < contentsNum; i++)
{ {
if (CONTENT_SIZE[i] > 0) if (CONTENT_SIZE[i] > 0)
{ {
@ -536,7 +560,7 @@ namespace TwlBackupBlock
Console.WriteLine("TMDブロックのハッシュが一致しません"); Console.WriteLine("TMDブロックのハッシュが一致しません");
return false; return false;
} }
for (int i = 0; i < MAX_CONTENTS; i++) for (int i = 0; i < contentsNum; i++)
{ {
if (CONTENT_SIZE[i] > 0) if (CONTENT_SIZE[i] > 0)
{ {
@ -560,7 +584,7 @@ namespace TwlBackupBlock
Console.WriteLine("publicセーブデータブロックのMACが一致しません"); Console.WriteLine("publicセーブデータブロックのMACが一致しません");
return false; return false;
} }
if (!CheckHash(blocks.publicSave, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE])) if (!CheckHash(blocks.publicSave, signatureBody.digest.section[indexPublicSave]))
{ {
Console.WriteLine("publicセーブデータブロックのハッシュが一致しません"); Console.WriteLine("publicセーブデータブロックのハッシュが一致しません");
return false; return false;
@ -571,7 +595,7 @@ namespace TwlBackupBlock
Console.WriteLine("サブバナーブロックの内容とMACが一致しません"); Console.WriteLine("サブバナーブロックの内容とMACが一致しません");
return false; return false;
} }
if (!CheckHash(blocks.subBanner, signatureBody.digest.section[(int)SectionIndex.SUB_BANNER])) if (!CheckHash(blocks.subBanner, signatureBody.digest.section[indexSubBanner]))
{ {
Console.WriteLine("サブバナーブロックのハッシュが一致しません"); Console.WriteLine("サブバナーブロックのハッシュが一致しません");
return false; return false;