From dbd09789ba98a7a905bdb10cd987683650342060 Mon Sep 17 00:00:00 2001 From: n2460 Date: Sat, 22 Oct 2011 11:54:05 +0000 Subject: [PATCH] =?UTF-8?q?TWLBackupBlock:WPS=E5=BD=A2=E5=BC=8F=E3=81=AE?= =?UTF-8?q?=E6=99=82=E3=82=82=E5=BE=A9=E5=8F=B7=E5=8C=96=E5=8F=8A=E3=81=B3?= =?UTF-8?q?=E6=A4=9C=E8=A8=BC=E3=81=8C=E8=A1=8C=E3=81=88=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@35 6b0af911-cb57-b745-895f-eec5701120e1 --- TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs | 132 ++++++++++++++++-- 1 file changed, 117 insertions(+), 15 deletions(-) diff --git a/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs b/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs index 6575065..c5e97d6 100644 --- a/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs +++ b/TwlBkpCheck/Windows/TWLBackupBlock/Utility.cs @@ -32,22 +32,56 @@ namespace TwlBackupBlock private const int BANNER_SIZE = 16 * 1024; private const int HEADER_SIZE = 240; - private const int SIGNATURE_SIZE = 1248; + private const int EX_HEADER_SIZE = 256; private const int LEGACY_HEADER_SIZE = 160; + private const int SIGNATURE_SIZE = 1248; + private const int EX_SIGNATURE_SIZE = 1280; 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; + private const int ENCRYPT_EX_HEADER_SIZE = EX_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; /// /// バックアップデータをブロックに分割して復号化をおこないます。 /// /// バックアップデータ。 /// データ本体の復号鍵。 + /// バックアップデータの形式。 /// 分割、復号化されたブロック。 - public static Blocks DecryptBackupData(byte[] data, byte[] key) + 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; + + switch (type) + { + case BkpType.NORMAL: + headerSize = HEADER_SIZE; + signatureSize = SIGNATURE_SIZE; + encryptHeaderSize = ENCRYPT_HEADER_SIZE; + encryptSignatureSize = ENCRYPT_SIGNATURE_SIZE; + break; + + case BkpType.WITH_PRIVATE_SAVE: + headerSize = EX_HEADER_SIZE; + signatureSize = EX_SIGNATURE_SIZE; + encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE; + encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE; + break; + } + if (data == null) { throw new ArgumentNullException("data"); @@ -57,7 +91,7 @@ namespace TwlBackupBlock throw new ArgumentNullException("key"); } { - int minDataSize = ENCRYPT_BANNER_SIZE + ENCRYPT_HEADER_SIZE + ENCRYPT_SIGNATURE_SIZE; + int minDataSize = ENCRYPT_BANNER_SIZE + encryptHeaderSize + encryptSignatureSize; if (data.Length < minDataSize) { string message = string.Format("data.Length < {0} (data.Length:{1})", data, minDataSize); @@ -76,7 +110,8 @@ namespace TwlBackupBlock using (var br = new BinaryReader(ms)) { blocks.banner.body = new Body(DecryptBlock(br, BANNER_SIZE, key, out blocks.banner.mac, out blocks.banner.iv)); - HeaderBody headerBody = new HeaderBody(DecryptBlock(br, HEADER_SIZE, key, out blocks.header.mac, out blocks.header.iv)); + HeaderBody headerBody = new HeaderBody( + DecryptBlock(br, headerSize, key, out blocks.header.mac, out blocks.header.iv), type); blocks.header.body = headerBody; if (!CheckSignature(headerBody)) @@ -84,9 +119,10 @@ namespace TwlBackupBlock throw new Exception("ヘッダブロックのシグネチャが正しくありません"); } - blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv)); + blocks.signature.body = new SignatureBody( + DecryptBlock(br, signatureSize, key, out blocks.signature.mac, out blocks.signature.iv), type); - // TODO : Legacy, WPS 対応 + // 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++) @@ -95,6 +131,11 @@ namespace TwlBackupBlock } int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE]; int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; + int PRIVATE_SAVE_SIZE = 0; + if (type == BkpType.WITH_PRIVATE_SAVE) + { + PRIVATE_SAVE_SIZE = (int)headerBody.privateSaveForWPS; + } 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++) @@ -108,8 +149,12 @@ namespace TwlBackupBlock blocks.content[i].body = null; } } - blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, key, out blocks.saveData.mac, out blocks.saveData.iv)); + blocks.publicSave.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, key, out blocks.publicSave.mac, out blocks.publicSave.iv)); blocks.subBanner.body = new Body(DecryptBlock(br, SUB_BANNER_SIZE, key, out blocks.subBanner.mac, out blocks.subBanner.iv)); + if (type == BkpType.WITH_PRIVATE_SAVE) + { + blocks.privateSave.body = new Body(DecryptBlock(br, PRIVATE_SAVE_SIZE, key, out blocks.privateSave.mac, out blocks.privateSave.iv)); + } Debug.Assert(ms.Position == data.Length); } @@ -344,9 +389,39 @@ namespace TwlBackupBlock /// 検証にかけるバックアップデータ。 /// データ本体の暗号鍵。 /// MACの鍵。 + /// バックアップの形式。 /// 検証に成功した場合はtrue。それ以外の場合はfalse。 - public static bool Verify(byte[] data, byte[] aesCbcKey, byte[] aesCmacKey) + 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; + + switch (type) + { + case BkpType.NORMAL: + headerSize = HEADER_SIZE; + signatureSize = SIGNATURE_SIZE; + encryptHeaderSize = ENCRYPT_HEADER_SIZE; + encryptSignatureSize = ENCRYPT_SIGNATURE_SIZE; + break; + + case BkpType.WITH_PRIVATE_SAVE: + headerSize = EX_HEADER_SIZE; + signatureSize = EX_SIGNATURE_SIZE; + encryptHeaderSize = ENCRYPT_EX_HEADER_SIZE; + encryptSignatureSize = ENCRYPT_EX_SIGNATURE_SIZE; + break; + } + if (data == null) { throw new ArgumentNullException("data"); @@ -362,7 +437,7 @@ namespace TwlBackupBlock } { - int minDataSize = ENCRYPT_BANNER_SIZE + ENCRYPT_HEADER_SIZE + ENCRYPT_SIGNATURE_SIZE; + int minDataSize = ENCRYPT_BANNER_SIZE + encryptHeaderSize + encryptSignatureSize; if (data.Length < minDataSize) { Console.WriteLine("バックアップファイルサイズがバナー+ヘッダ+署名ブロック未満です"); @@ -376,9 +451,11 @@ namespace TwlBackupBlock using (var br = new BinaryReader(ms)) { blocks.banner.body = new Body(DecryptBlock(br, BANNER_SIZE, aesCbcKey, out blocks.banner.mac, out blocks.banner.iv)); - HeaderBody headerBody = new HeaderBody(DecryptBlock(br, HEADER_SIZE, aesCbcKey, out blocks.header.mac, out blocks.header.iv)); + HeaderBody headerBody = new HeaderBody( + DecryptBlock(br, headerSize, aesCbcKey, out blocks.header.mac, out blocks.header.iv), type); blocks.header.body = headerBody; - SignatureBody signatureBody = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, aesCbcKey, out blocks.signature.mac, out blocks.signature.iv)); + SignatureBody signatureBody = new SignatureBody( + DecryptBlock(br, signatureSize, aesCbcKey, out blocks.signature.mac, out blocks.signature.iv), type); blocks.signature.body = signatureBody; if (!CheckMac(blocks.header, aesCmacKey, blocks.header.mac)) @@ -413,7 +490,7 @@ namespace TwlBackupBlock return false; } - // TODO : 複数コンテンツ対応 + // 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++) @@ -422,6 +499,11 @@ namespace TwlBackupBlock } int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE]; int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; + int PRIVATE_SAVE_SIZE = 0; + if (type == BkpType.WITH_PRIVATE_SAVE) + { + PRIVATE_SAVE_SIZE = (int)headerBody.privateSaveForWPS; + } int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) + RoundUp(PUBLIC_SAVE_SIZE, ROUND_SCALE) + RoundUp(SUB_BANNER_SIZE, ROUND_SCALE) + @@ -433,6 +515,11 @@ namespace TwlBackupBlock restSize += RoundUp(CONTENT_SIZE[i], ROUND_SCALE) + AES_SIGN_HEADER_SIZE; } } + if (type == BkpType.WITH_PRIVATE_SAVE) + { + restSize += RoundUp(PRIVATE_SAVE_SIZE, ROUND_SCALE) + AES_SIGN_HEADER_SIZE; + } + if (data.Length - ms.Position != restSize) { Console.WriteLine("TMD、コンテンツ、publicセーブデータ、サブバナーブロックサイズが実際のサイズと一致しません"); @@ -467,13 +554,13 @@ namespace TwlBackupBlock } } } - 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)) + blocks.publicSave.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, aesCbcKey, out blocks.publicSave.mac, out blocks.publicSave.iv)); + if (!CheckMac(blocks.publicSave, aesCmacKey, blocks.publicSave.mac)) { Console.WriteLine("publicセーブデータブロックのMACが一致しません"); return false; } - if (!CheckHash(blocks.saveData, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE])) + if (!CheckHash(blocks.publicSave, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE])) { Console.WriteLine("publicセーブデータブロックのハッシュが一致しません"); return false; @@ -489,6 +576,21 @@ namespace TwlBackupBlock Console.WriteLine("サブバナーブロックのハッシュが一致しません"); return false; } + // WITH_PRIVATE_SAVE の時は private save も対象 + if (type == BkpType.WITH_PRIVATE_SAVE) + { + blocks.privateSave.body = new Body(DecryptBlock(br, PRIVATE_SAVE_SIZE, aesCbcKey, out blocks.privateSave.mac, out blocks.privateSave.iv)); + if (!CheckMac(blocks.privateSave, aesCmacKey, blocks.privateSave.mac)) + { + Console.WriteLine("privateセーブデータブロックの内容とMACが一致しません"); + return false; + } + if (!CheckHash(blocks.privateSave, signatureBody.digest.section[(int)SectionIndex.PRIVATE_SAVE])) + { + Console.WriteLine("privateセーブデータブロックのハッシュが一致しません"); + return false; + } + } Debug.Assert(ms.Position == data.Length); }