mirror of
https://github.com/rvtr/ctr_test_tools.git
synced 2025-06-19 09:05:31 -04:00
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:
parent
4978389346
commit
12cf32bf6b
@ -23,6 +23,10 @@ namespace TwlBackupBlock
|
||||
// for WithPrivateSave
|
||||
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 UInt16 companyCode;
|
||||
public UInt16 version;
|
||||
@ -41,6 +45,10 @@ namespace TwlBackupBlock
|
||||
public UInt32 privateSaveForWPS;
|
||||
public readonly Byte[] reservedForWPS;
|
||||
|
||||
// for Legacy
|
||||
public UInt32 contentIdForLegacy;
|
||||
public UInt16 contentIndexForLegacy;
|
||||
|
||||
private BkpType type;
|
||||
private int headerSize;
|
||||
|
||||
@ -72,12 +80,19 @@ 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];
|
||||
if (type != BkpType.LEGACY)
|
||||
{
|
||||
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();
|
||||
reserved = new Byte[RESERVED_SIZE];
|
||||
|
||||
if (type == BkpType.WITH_PRIVATE_SAVE)
|
||||
{
|
||||
reservedForWPS = new Byte[RESERVED_SIZE_FOR_WPS];
|
||||
@ -154,7 +169,6 @@ namespace TwlBackupBlock
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
// TODO : Legacy 対応
|
||||
bw.Write(signature);
|
||||
bw.Write(companyCode);
|
||||
bw.Write(version);
|
||||
@ -166,16 +180,33 @@ namespace TwlBackupBlock
|
||||
{
|
||||
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(headerVersion);
|
||||
if (type == BkpType.LEGACY)
|
||||
{
|
||||
bw.Write(contentIndexForLegacy);
|
||||
}
|
||||
if (type != BkpType.LEGACY)
|
||||
{
|
||||
bw.Write(headerVersion);
|
||||
}
|
||||
bw.Write(reserved);
|
||||
if (type == BkpType.WITH_PRIVATE_SAVE)
|
||||
{
|
||||
@ -204,7 +235,6 @@ namespace TwlBackupBlock
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var br = new ExtBinaryReader(ms))
|
||||
{
|
||||
// TODO : Legacy 対応
|
||||
br.Read(ref signature);
|
||||
br.Read(ref companyCode);
|
||||
br.Read(ref version);
|
||||
@ -213,14 +243,31 @@ namespace TwlBackupBlock
|
||||
br.Read(ref titleId);
|
||||
br.Read(ref requiredSize);
|
||||
br.Read(fileSizes);
|
||||
br.Read(contentId);
|
||||
br.Read(contentIndex);
|
||||
if (type != BkpType.LEGACY)
|
||||
{
|
||||
br.Read(contentId);
|
||||
}
|
||||
else
|
||||
{
|
||||
br.Read(ref contentIdForLegacy);
|
||||
}
|
||||
if (type != BkpType.LEGACY)
|
||||
{
|
||||
br.Read(contentIndex);
|
||||
}
|
||||
{
|
||||
byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
|
||||
br.Read(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);
|
||||
if (type == BkpType.WITH_PRIVATE_SAVE)
|
||||
{
|
||||
|
@ -23,6 +23,17 @@ namespace TwlBackupBlock
|
||||
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 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_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_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_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>
|
||||
/// バックアップデータをブロックに分割して復号化をおこないます。
|
||||
@ -53,17 +66,13 @@ namespace TwlBackupBlock
|
||||
/// <returns>分割、復号化されたブロック。</returns>
|
||||
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 signatureSize = 0;
|
||||
int encryptHeaderSize = 0;
|
||||
int encryptSignatureSize = 0;
|
||||
int contentsNum = MAX_CONTENTS;
|
||||
int indexPublicSave = (int)SectionIndexLegacy.PUBLIC_SAVE;
|
||||
int indexSubBanner = (int)SectionIndexLegacy.SUB_BANNER;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@ -80,6 +89,16 @@ namespace TwlBackupBlock
|
||||
encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE;
|
||||
encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE;
|
||||
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)
|
||||
@ -122,15 +141,14 @@ namespace TwlBackupBlock
|
||||
blocks.signature.body = new SignatureBody(
|
||||
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[] CONTENT_SIZE = new int[MAX_CONTENTS];
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
int[] CONTENT_SIZE = new int[contentsNum];
|
||||
for (int i = 0; i < contentsNum; i++)
|
||||
{
|
||||
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
|
||||
}
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[indexPublicSave];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[indexSubBanner];
|
||||
int PRIVATE_SAVE_SIZE = 0;
|
||||
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));
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
for (int i = 0; i < contentsNum; i++)
|
||||
{
|
||||
if (CONTENT_SIZE[i] > 0)
|
||||
{
|
||||
@ -393,17 +411,13 @@ namespace TwlBackupBlock
|
||||
/// <returns>検証に成功した場合はtrue。それ以外の場合はfalse。</returns>
|
||||
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 signatureSize = 0;
|
||||
int encryptHeaderSize = 0;
|
||||
int encryptSignatureSize = 0;
|
||||
int contentsNum = MAX_CONTENTS;
|
||||
int indexPublicSave = (int)SectionIndex.PUBLIC_SAVE;
|
||||
int indexSubBanner = (int)SectionIndex.SUB_BANNER;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@ -420,6 +434,16 @@ namespace TwlBackupBlock
|
||||
encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE;
|
||||
encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE;
|
||||
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)
|
||||
@ -492,13 +516,13 @@ namespace TwlBackupBlock
|
||||
|
||||
// TODO : Legacy 対応
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
|
||||
int[] CONTENT_SIZE = new int[MAX_CONTENTS];
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
int[] CONTENT_SIZE = new int[contentsNum];
|
||||
for (int i = 0; i < contentsNum; i++)
|
||||
{
|
||||
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
|
||||
}
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[indexPublicSave];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[indexSubBanner];
|
||||
int PRIVATE_SAVE_SIZE = 0;
|
||||
if (type == BkpType.WITH_PRIVATE_SAVE)
|
||||
{
|
||||
@ -508,7 +532,7 @@ namespace TwlBackupBlock
|
||||
int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) +
|
||||
RoundUp(PUBLIC_SAVE_SIZE, ROUND_SCALE) + RoundUp(SUB_BANNER_SIZE, ROUND_SCALE) +
|
||||
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)
|
||||
{
|
||||
@ -536,7 +560,7 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("TMDブロックのハッシュが一致しません");
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
for (int i = 0; i < contentsNum; i++)
|
||||
{
|
||||
if (CONTENT_SIZE[i] > 0)
|
||||
{
|
||||
@ -560,7 +584,7 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("publicセーブデータブロックのMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.publicSave, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE]))
|
||||
if (!CheckHash(blocks.publicSave, signatureBody.digest.section[indexPublicSave]))
|
||||
{
|
||||
Console.WriteLine("publicセーブデータブロックのハッシュが一致しません");
|
||||
return false;
|
||||
@ -571,7 +595,7 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("サブバナーブロックの内容とMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.subBanner, signatureBody.digest.section[(int)SectionIndex.SUB_BANNER]))
|
||||
if (!CheckHash(blocks.subBanner, signatureBody.digest.section[indexSubBanner]))
|
||||
{
|
||||
Console.WriteLine("サブバナーブロックのハッシュが一致しません");
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user