TWLBackupBlock:HeaderBody に WithPrivateSave 形式のフィールドと処理の追加。

SignatureBody に WithPrivateSave 形式の処理の追加。
LegacyHeaderBody の削除。

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@34 6b0af911-cb57-b745-895f-eec5701120e1
This commit is contained in:
n2460 2011-10-22 11:53:00 +00:00
parent 4cade41cb1
commit 76257fc66c
4 changed files with 114 additions and 223 deletions

View File

@ -9,7 +9,9 @@ namespace TwlBackupBlock
/// </summary> /// </summary>
public class HeaderBody : AbstractBody public class HeaderBody : AbstractBody
{ {
public const int HEADER_SIZE = 240; public const int NORMAL_HEADER_SIZE = 240;
public const int EX_HEADER_SIZE = 256;
public const int LEGACY_HEADER_SIZE = 160;
public const int UNIQUE_ID_SIZE = 32; public const int UNIQUE_ID_SIZE = 32;
public const int HARDWARE_ID_SIZE = 16; public const int HARDWARE_ID_SIZE = 16;
@ -18,6 +20,9 @@ namespace TwlBackupBlock
public const int TMD_RESERVED_SIZE = 62; public const int TMD_RESERVED_SIZE = 62;
public const int RESERVED_SIZE = 13; public const int RESERVED_SIZE = 13;
// for WithPrivateSave
public const int RESERVED_SIZE_FOR_WPS = 12;
public UInt32 signature; public UInt32 signature;
public UInt16 companyCode; public UInt16 companyCode;
public UInt16 version; public UInt16 version;
@ -32,15 +37,36 @@ namespace TwlBackupBlock
public Byte headerVersion; public Byte headerVersion;
public readonly Byte[] reserved; public readonly Byte[] reserved;
public HeaderBody(byte[] data) // for WithPrivateSave
public UInt32 privateSaveForWPS;
public readonly Byte[] reservedForWPS;
private BkpType type;
private int headerSize;
public HeaderBody(byte[] data, BkpType type)
{ {
this.type = type;
switch (this.type)
{
case BkpType.NORMAL:
headerSize = NORMAL_HEADER_SIZE;
break;
case BkpType.WITH_PRIVATE_SAVE:
headerSize = EX_HEADER_SIZE;
break;
case BkpType.LEGACY:
headerSize = LEGACY_HEADER_SIZE;
break;
}
if (data == null) if (data == null)
{ {
throw new ArgumentNullException("data"); throw new ArgumentNullException("data");
} }
if (data.Length != HEADER_SIZE) if (data.Length != headerSize)
{ {
string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", HEADER_SIZE, data.Length); string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", headerSize, data.Length);
throw new ArgumentException("data", message); throw new ArgumentException("data", message);
} }
@ -52,6 +78,11 @@ namespace TwlBackupBlock
tmdReserved = new TmdReserved(); tmdReserved = new TmdReserved();
reserved = new Byte[RESERVED_SIZE]; reserved = new Byte[RESERVED_SIZE];
if (type == BkpType.WITH_PRIVATE_SAVE)
{
reservedForWPS = new Byte[RESERVED_SIZE_FOR_WPS];
}
SetBytes(data); SetBytes(data);
} }
@ -59,7 +90,7 @@ namespace TwlBackupBlock
{ {
get get
{ {
if (index < 0 || index >= HEADER_SIZE) if (index < 0 || index >= headerSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -67,7 +98,7 @@ namespace TwlBackupBlock
} }
set set
{ {
if (index < 0 || index >= HEADER_SIZE) if (index < 0 || index >= headerSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -79,7 +110,7 @@ namespace TwlBackupBlock
{ {
get get
{ {
return HEADER_SIZE; return headerSize;
} }
} }
@ -90,7 +121,7 @@ namespace TwlBackupBlock
/// <returns><paramref name="index"/>で指定したバイト</returns> /// <returns><paramref name="index"/>で指定したバイト</returns>
public byte ReadByte(int index) public byte ReadByte(int index)
{ {
if (index < 0 || index >= HEADER_SIZE) if (index < 0 || index >= headerSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -106,7 +137,7 @@ namespace TwlBackupBlock
/// <param name="b">上書きに使うバイト。</param> /// <param name="b">上書きに使うバイト。</param>
public void WriteByte(int index, byte b) public void WriteByte(int index, byte b)
{ {
if (index < 0 || index >= HEADER_SIZE) if (index < 0 || index >= headerSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -118,11 +149,12 @@ namespace TwlBackupBlock
public override byte[] GetBytes() public override byte[] GetBytes()
{ {
byte[] bytes = new byte[HEADER_SIZE]; byte[] bytes = new byte[headerSize];
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);
@ -145,8 +177,13 @@ namespace TwlBackupBlock
bw.Write(tmdReserved.GetBytes()); bw.Write(tmdReserved.GetBytes());
bw.Write(headerVersion); bw.Write(headerVersion);
bw.Write(reserved); bw.Write(reserved);
if (type == BkpType.WITH_PRIVATE_SAVE)
{
bw.Write(privateSaveForWPS);
bw.Write(reservedForWPS);
}
Debug.Assert(ms.Position == HEADER_SIZE); Debug.Assert(ms.Position == headerSize);
} }
return bytes; return bytes;
@ -158,15 +195,16 @@ namespace TwlBackupBlock
{ {
throw new ArgumentNullException("bytes"); throw new ArgumentNullException("bytes");
} }
if (bytes.Length != HEADER_SIZE) if (bytes.Length != headerSize)
{ {
string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", HEADER_SIZE, bytes.Length); string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", headerSize, bytes.Length);
throw new ArgumentException("bytes", message); throw new ArgumentException("bytes", message);
} }
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);
@ -184,14 +222,19 @@ namespace TwlBackupBlock
} }
br.Read(ref headerVersion); br.Read(ref headerVersion);
br.Read(reserved); br.Read(reserved);
if (type == BkpType.WITH_PRIVATE_SAVE)
{
br.Read(ref privateSaveForWPS);
br.Read(reservedForWPS);
}
Debug.Assert(ms.Position == HEADER_SIZE); Debug.Assert(ms.Position == headerSize);
} }
} }
public override object Clone() public override object Clone()
{ {
return new HeaderBody(GetBytes()); return new HeaderBody(GetBytes(), type);
} }
} }
} }

View File

@ -1,185 +0,0 @@
using System;
using System.IO;
using System.Diagnostics;
namespace TwlBackupBlock
{
/// <summary>
/// ヘッダブロックのデータ本体。
/// </summary>
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;
}
}
/// <summary>
/// 指定したバイトを取得します。
/// </summary>
/// <param name="index">取得したいバイトのインデックス。</param>
/// <returns><paramref name="index"/>で指定したバイト</returns>
public byte ReadByte(int index)
{
if (index < 0 || index >= HEADER_SIZE)
{
throw new ArgumentException("index");
}
// TODO 処理が遅ければ効率化
byte[] bytes = GetBytes();
return bytes[index];
}
/// <summary>
/// 指定したバイトを書き換えます。
/// </summary>
/// <param name="index">書き換えたいバイトのインデックス。</param>
/// <param name="b">上書きに使うバイト。</param>
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());
}
}
}

View File

@ -10,22 +10,38 @@ namespace TwlBackupBlock
public class TwlBackupHashSet public class TwlBackupHashSet
{ {
public const int HASH_SIZE = 32; public const int HASH_SIZE = 32;
public const int NUM_OF_SECTION = 11; public const int NUM_OF_SECTION_NORMAL = 11;
public const int NUM_OF_LEGACY_SECTION = 4; public const int NUM_OF_SECTION_EX = 12;
public const int NUM_OF_SECTION_LEGACY = 4;
public readonly byte[] banner; public readonly byte[] banner;
public readonly byte[] header; public readonly byte[] header;
public readonly byte[][] section; public readonly byte[][] section;
private BkpType type;
/// <summary> /// <summary>
/// コンストラクタ。 /// コンストラクタ。
/// </summary> /// </summary>
public TwlBackupHashSet(bool isLegacy = false) public TwlBackupHashSet(BkpType type)
{ {
this.type = type;
banner = new byte[HASH_SIZE]; banner = new byte[HASH_SIZE];
header = new byte[HASH_SIZE]; header = new byte[HASH_SIZE];
section = isLegacy ?
new byte[NUM_OF_LEGACY_SECTION][] : new byte[NUM_OF_SECTION][]; if (this.type == BkpType.NORMAL)
{
section = new byte[NUM_OF_SECTION_NORMAL][];
}
else if (this.type == BkpType.WITH_PRIVATE_SAVE)
{
section = new byte[NUM_OF_SECTION_EX][];
}
else if (this.type == BkpType.LEGACY)
{
section = new byte[NUM_OF_SECTION_LEGACY][];
}
for (int i = 0; i < section.Length; i++) for (int i = 0; i < section.Length; i++)
{ {
section[i] = new byte[HASH_SIZE]; section[i] = new byte[HASH_SIZE];
@ -37,8 +53,9 @@ namespace TwlBackupBlock
/// </summary> /// </summary>
public class SignatureBody : AbstractBody public class SignatureBody : AbstractBody
{ {
public const int SIGNATURE_SIZE = 1248; public const int SIGNATURE_SIZE_NORMAL = 1248;
public const int LEGACY_SIGNATURE_SIZE = 1024; public const int SIGNATURE_SIZE_EX = 1280;
public const int SIGNATURE_SIZE_LEGACY = 1024;
public const int ECC_SIGN_SIZE = 60; public const int ECC_SIGN_SIZE = 60;
public const int ECC_CERT_SIZE = 384; public const int ECC_CERT_SIZE = 384;
@ -48,19 +65,36 @@ namespace TwlBackupBlock
public readonly byte[][] cert; public readonly byte[][] cert;
public UInt32 reserved; public UInt32 reserved;
public SignatureBody(byte[] data) private BkpType type;
private int signatureSize;
public SignatureBody(byte[] data, BkpType type)
{ {
this.type = type;
switch (this.type)
{
case BkpType.NORMAL:
signatureSize = SIGNATURE_SIZE_NORMAL;
break;
case BkpType.WITH_PRIVATE_SAVE:
signatureSize = SIGNATURE_SIZE_EX;
break;
case BkpType.LEGACY:
signatureSize = SIGNATURE_SIZE_LEGACY;
break;
}
if (data == null) if (data == null)
{ {
throw new ArgumentNullException("data"); throw new ArgumentNullException("data");
} }
if (data.Length != SIGNATURE_SIZE) if (data.Length != signatureSize)
{ {
string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", SIGNATURE_SIZE, data.Length); string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", signatureSize, data.Length);
throw new ArgumentException("data", message); throw new ArgumentException("data", message);
} }
digest = new TwlBackupHashSet(); digest = new TwlBackupHashSet(this.type);
sign = new byte[ECC_SIGN_SIZE]; sign = new byte[ECC_SIGN_SIZE];
cert = new byte[2][]; cert = new byte[2][];
for (int i = 0; i < cert.Length; i++) for (int i = 0; i < cert.Length; i++)
@ -75,7 +109,7 @@ namespace TwlBackupBlock
{ {
get get
{ {
if (index < 0 || index >= SIGNATURE_SIZE) if (index < 0 || index >= signatureSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -83,7 +117,7 @@ namespace TwlBackupBlock
} }
set set
{ {
if (index < 0 || index >= SIGNATURE_SIZE) if (index < 0 || index >= signatureSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -95,7 +129,7 @@ namespace TwlBackupBlock
{ {
get get
{ {
return SIGNATURE_SIZE; return signatureSize;
} }
} }
@ -106,7 +140,7 @@ namespace TwlBackupBlock
/// <returns><paramref name="index"/>で指定したバイト</returns> /// <returns><paramref name="index"/>で指定したバイト</returns>
public byte ReadByte(int index) public byte ReadByte(int index)
{ {
if (index < 0 || index >= SIGNATURE_SIZE) if (index < 0 || index >= signatureSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -122,7 +156,7 @@ namespace TwlBackupBlock
/// <param name="b">上書きに使うバイト。</param> /// <param name="b">上書きに使うバイト。</param>
public void WriteByte(int index, byte b) public void WriteByte(int index, byte b)
{ {
if (index < 0 || index >= SIGNATURE_SIZE) if (index < 0 || index >= signatureSize)
{ {
throw new ArgumentException("index"); throw new ArgumentException("index");
} }
@ -134,7 +168,7 @@ namespace TwlBackupBlock
public override byte[] GetBytes() public override byte[] GetBytes()
{ {
byte[] bytes = new byte[SIGNATURE_SIZE]; byte[] bytes = new byte[signatureSize];
using (var ms = new MemoryStream(bytes)) using (var ms = new MemoryStream(bytes))
using (var bw = new BinaryWriter(ms)) using (var bw = new BinaryWriter(ms))
@ -152,7 +186,7 @@ namespace TwlBackupBlock
} }
bw.Write(reserved); bw.Write(reserved);
Debug.Assert(ms.Position == SIGNATURE_SIZE); Debug.Assert(ms.Position == signatureSize);
} }
return bytes; return bytes;
@ -164,9 +198,9 @@ namespace TwlBackupBlock
{ {
throw new ArgumentNullException("bytes"); throw new ArgumentNullException("bytes");
} }
if (bytes.Length != SIGNATURE_SIZE) if (bytes.Length != signatureSize)
{ {
string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", SIGNATURE_SIZE, bytes.Length); string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", signatureSize, bytes.Length);
throw new ArgumentException("bytes", message); throw new ArgumentException("bytes", message);
} }
@ -186,13 +220,13 @@ namespace TwlBackupBlock
} }
br.Read(ref reserved); br.Read(ref reserved);
Debug.Assert(ms.Position == SIGNATURE_SIZE); Debug.Assert(ms.Position == signatureSize);
} }
} }
public override object Clone() public override object Clone()
{ {
return new SignatureBody(GetBytes()); return new SignatureBody(GetBytes(), type);
} }
} }
} }

View File

@ -58,7 +58,6 @@
<Compile Include="AesCmac.cs" /> <Compile Include="AesCmac.cs" />
<Compile Include="Body.cs" /> <Compile Include="Body.cs" />
<Compile Include="ExtBinaryReader.cs" /> <Compile Include="ExtBinaryReader.cs" />
<Compile Include="LegacyHeaderBody.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>