From 598f26393268e3d03e212f61c0b80060505e1f7d Mon Sep 17 00:00:00 2001 From: yutaka Date: Fri, 11 Apr 2008 07:23:14 +0000 Subject: [PATCH] =?UTF-8?q?DS=E3=83=8F=E3=83=83=E3=82=B7=E3=83=A5=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=96=E3=83=AB=E6=A4=9C=E8=A8=BC=E3=82=B5=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1109 b08762b0-b915-fc4b-9d8c-17b2551a87ff --- .../CheckDSHashTable/CheckDSHashTable.rsf | 249 +++++++++++ build/tests/CheckDSHashTable/Makefile | 52 +++ build/tests/CheckDSHashTable/src/dht.c | 407 ++++++++++++++++++ build/tests/CheckDSHashTable/src/main.c | 193 +++++++++ include/sysmenu/dht/dht.h | 84 ++++ include/sysmenu/dht/dht_format.h | 76 ++++ 6 files changed, 1061 insertions(+) create mode 100644 build/tests/CheckDSHashTable/CheckDSHashTable.rsf create mode 100644 build/tests/CheckDSHashTable/Makefile create mode 100644 build/tests/CheckDSHashTable/src/dht.c create mode 100644 build/tests/CheckDSHashTable/src/main.c create mode 100644 include/sysmenu/dht/dht.h create mode 100644 include/sysmenu/dht/dht_format.h diff --git a/build/tests/CheckDSHashTable/CheckDSHashTable.rsf b/build/tests/CheckDSHashTable/CheckDSHashTable.rsf new file mode 100644 index 00000000..8b3e3892 --- /dev/null +++ b/build/tests/CheckDSHashTable/CheckDSHashTable.rsf @@ -0,0 +1,249 @@ +#---------------------------------------------------------------------------- +# Project: TwlSDK - include +# File: ROM-TS.rsf +# +# Copyright 2007 Nintendo. All rights reserved. +# +# These coded insructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- +# +# TWL ROM SPEC FILE +# + +Arm9 +{ + Static "$(MAKEROM_ARM9:r).TWL.FLX.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.TWL.FLX.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.TWL.FLX.sbin$(COMPSUFFIX9)" + Elf "$(MAKEROM_ARM9:r).tef" +} + +Arm7 +{ + Static "$(MAKEROM_ARM7_BASE:r).TWL.FLX.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.TWL.FLX.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.TWL.FLX.sbin$(COMPSUFFIX7)" + Elf "$(MAKEROM_ARM7_BASE:r).tef" +} + +Arm9.Ltd +{ + Static "$(MAKEROM_ARM9:r).TWL.LTD.sbin$(COMPSUFFIX9)" + OverlayDefs "$(MAKEROM_ARM9:r)_defs.TWL.LTD.sbin$(COMPSUFFIX9)" + OverlayTable "$(MAKEROM_ARM9:r)_table.TWL.LTD.sbin$(COMPSUFFIX9)" +} + +Arm7.Ltd +{ + Static "$(MAKEROM_ARM7_BASE:r).TWL.LTD.sbin$(COMPSUFFIX7)" + OverlayDefs "$(MAKEROM_ARM7_BASE:r)_defs.TWL.LTD.sbin$(COMPSUFFIX7)" + OverlayTable "$(MAKEROM_ARM7_BASE:r)_table.TWL.LTD.sbin$(COMPSUFFIX7)" +} + +Property +{ + ### + ### Settings for FinalROM + ### + #### BEGIN + # + # TITLE NAME: Your product name within 12bytes + # + #TitleName "YourAppName" + + # + # MAKER CODE: Your company ID# in 2 ascii words + # issued by NINTENDO + # + #MakerCode "00" + + # + # REMASTER VERSION: Mastering version + # + #RomVersion 0 + + # + # ROM SPEED TYPE: [MROM/1TROM/UNDEFINED] + # + RomSpeedType $(MAKEROM_ROMSPEED) + + # + # ROM SIZE: in bit [64M/128M/256M/512M/1G/2G] + # + #RomSize 128M + #RomSize 256M + + # + # ROM PADDING: TRUE if finalrom + # + #RomFootPadding TRUE + + # + # ROM HEADER TEMPLATE: Provided to every product by NINTENDO + # + #RomHeaderTemplate ./etc/rom_header.template.sbin + + # + # BANNER FILE: generated from Banner Spec File + # + #BannerFile ./etc/myGameBanner.bnr + BannerFile $(TWLSDK_ROOT)/include/twl/specfiles/default.bnr + + # + # Permit LandingNormalJump: for TWL "ApplicationJump" function [TRUE/FALSE] + # + #PermitLandingNormalJump FALSE + + # + # Permit LandingTmpJump: for TWL "ApplicationJump" function [TRUE/FALSE] + # + #PermitLandingTmpJump FALSE + + ### + ### Setting for TWL + ### + + # + # ROM HEADER Ltd: Provided to every product by NINTENDO + # + RomHeaderLtd $(TWLSDK_ROOT)/tools/bin/rom_header.LTD.sbin + + # + # Digest parameters: + # + DigestParam 1024 32 + + # + # WRAM mapping: [MAP_BB_HYB/MAP_BB_LTD/MAP_TS_HYB/MAP_TS_LTD + # MAP2_BB_HYB/MAP2_BB_LTD/MAP2_TS_HYB/MAP2_TS_LTD] + # don't have to edit + # + WramMapping $(MAKEROM_WRAM_MAPPING) + + # + # CardRegion: card region [Japan/America/Europe/Australia/China/Korea] + # + CardRegion Japan + + # + # CommonClientKey: launcher deliver common client Key [TRUE/FALSE] + # + #CommonClientKey FALSE + + # + # HwAESSlotB: launcher deliver HW AES slot B setting [TRUE/FALSE] + # + #HwAESSlotB FALSE + + # + # HwAESSlotC: launcher deliver HW AES slot C setting [TRUE/FALSE] + # + #HwAESSlotC FALSE + + # + # SDCardAccess: sd card access control [TRUE/FALSE] + # + #SDCardAccess FALSE + + # + # NANDAccess: NAND access control [TRUE/FALSE] + # + #NANDAccess FALSE + + # + # Codec mode: + # don't have to edit + # + CodecMode $(MAKEROM_CODEC_MODE) + + # + # Disp WiFiConnection Icon for Launcher [TRUE/FALSE] + # + #WiFiConnectionIcon FALSE + + # + # Disp DSWireless Icon for Launcher [TRUE/FALSE] + # + #DSWirelessIcon FALSE + + ### + #### END +} + +AppendProperty +{ + # + # Publisher : "Nintendo" + # don't have to edit + Publisher Nintendo + + # + # Application type : [USER/SYSTEM] + # don't have to edit + AppType User + + # + # launch title on the launcher : [TRUE/FALSE] + # don't have to edit + Launch TRUE + + # + # Boot allowed Media: [GameCard] + # + Media GameCard + + # + # Data only title : [TRUE/FALSE] + # don't have to edit + DataOnly FALSE + + # + # Secure title : [TRUE/FALSE] + # don't have to edit + Secure FALSE + + # + # GameCode for TitleID : Your GameCode in 4 ascii words + # + #GameCode ABCJ + + # + # Public save data size: [0K/16K/32K/64K/128K/256K/512K/1M/2M/4M] + # + #PublicSaveDataSize 32K + + # + # Private save data size: [0K/16K/32K/64K/128K/256K/512K/1M/2M/4M] + # + #PrivateSaveDataSize 16K + + # + # Enable SubBannerFile + #SubBannerFile TRUE +} + +RomSpec +{ + Offset 0x00000000 + Segment ALL + HostRoot $(MAKEROM_DTH_ROOT) + Root /sign + File DSHashTable.bin + HostRoot $(MAKEROM_SRL_ROOT) + Root /srl +# File NA22E0.035 # 1st +# File NA22J0.024 # 2nd +# File NYZYE0.E81 # last-1 +# File NYZZJ0.L57 # last + File NYRVJ0.J30 # max number of overlaies + File NALKJ1.879 # max overlay size + File NA39J0.357 # mario kart +} diff --git a/build/tests/CheckDSHashTable/Makefile b/build/tests/CheckDSHashTable/Makefile new file mode 100644 index 00000000..1edefe22 --- /dev/null +++ b/build/tests/CheckDSHashTable/Makefile @@ -0,0 +1,52 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: TwlIPL - tests - CheckDSHashTable +# File: Makefile +# +# Copyright 2008 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- + +SUBDIRS = + +#---------------------------------------------------------------------------- + +TARGET_PLATFORM := TWL +TARGET_FIRM := SYSTEMMENU +override TWL_ARCHGEN := LIMITED + +SRCS = main.c dht.c +LINCLUDES = include +TARGET_BIN = CheckDSHashTable.srl +ROM_SPEC = CheckDSHashTable.rsf + +ifeq ($(TWL_IPL_RED_PRIVATE_ROOT),) +DS_HASH_TABLE_ROOT = data +else +DS_HASH_TABLE_ROOT = $(TWL_IPL_RED_PRIVATE_ROOT)/build/tools/MakeDSHashTable +endif +DS_HASH_TABLE_SRL_ROOT ?= D:/SRL + +include $(TWL_IPL_RED_ROOT)/build/buildtools/commondefs + +MAKEROM_FLAGS += -DMAKEROM_DTH_ROOT=$(DS_HASH_TABLE_ROOT) \ + -DMAKEROM_SRL_ROOT=$(DS_HASH_TABLE_SRL_ROOT) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +#---------------------------------------------------------------------------- +include $(TWLSDK_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/build/tests/CheckDSHashTable/src/dht.c b/build/tests/CheckDSHashTable/src/dht.c new file mode 100644 index 00000000..454656de --- /dev/null +++ b/build/tests/CheckDSHashTable/src/dht.c @@ -0,0 +1,407 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - DHT + File: dht.c + + Copyright 2007 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +#define HASH_PATH "/sign/DSHashTable.bin" + +/* + 定義すると処理時間を表示する +*/ +#define PRINT_PROFILE + +#ifdef PRINT_PROFILE +static int count; +static OSTick profile[0x10]; +#define PROFILE_INIT() (count = 0) +#define PROFILE_COUNT() (profile[count++] = OS_GetTick()) +#else +#define PROFILE_INIT() ((void)0) +#define PROFILE_COUNT() ((void)0) +#define +#endif + +static const u8 g_pubkey_DER[ 0xa2 ] = { + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc7, 0xf4, 0x1d, + 0x27, 0x3f, 0xe8, 0xae, 0x7f, 0x7c, 0xbc, 0x9a, 0xae, 0x09, 0x8d, 0x19, 0x26, 0x2e, 0x90, 0x04, + 0x03, 0x13, 0x93, 0xbc, 0xb2, 0xe0, 0x8b, 0x1f, 0x85, 0x48, 0xf5, 0xf6, 0x94, 0x69, 0x3e, 0x05, + 0x1b, 0x97, 0x85, 0x44, 0x6d, 0xa3, 0xcd, 0xa8, 0x01, 0xfe, 0xdc, 0x77, 0x5d, 0xd1, 0xb1, 0x36, + 0x21, 0xfc, 0x80, 0xe8, 0xa6, 0x0e, 0xde, 0x59, 0x76, 0xca, 0x96, 0xcc, 0x87, 0x4c, 0xc3, 0x90, + 0xc6, 0x3b, 0xc8, 0x17, 0x9d, 0x2d, 0xac, 0x45, 0xbc, 0xa7, 0x15, 0xb2, 0xe3, 0xd7, 0x76, 0xfa, + 0x09, 0x8c, 0x55, 0x09, 0x22, 0x95, 0x4b, 0xe7, 0xde, 0xc0, 0x82, 0xf2, 0x02, 0x1a, 0x8a, 0x42, + 0x38, 0x7f, 0xbb, 0x31, 0xd6, 0xa8, 0x36, 0xdc, 0x8d, 0x2c, 0x42, 0x56, 0x51, 0xc1, 0xa3, 0x30, + 0x21, 0x30, 0xef, 0x06, 0x72, 0x0c, 0xa6, 0x55, 0xb7, 0x4f, 0x30, 0x35, 0x1b, 0x02, 0x03, 0x01, + 0x00, 0x01 +}; + +static const u8 hmac_key[] = DHT_HMAC_KEY; + + +/* + 自家製bsearch +*/ + +static void *bsearch(const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *, const void *)) +{ + u32 left = 0; + u32 right = nmemb; + + if ( compar((u8*)base + size * (right - 1), key) < 0 ) + { + return NULL; + } + if ( compar((u8*)base + size * left, key) > 0 ) + { + return NULL; + } + + while (left <= right) + { + u32 mid = (left + right) >> 1; + const void* data = (u8*)base + size * mid; + int result = compar(data, key); +//OS_TPrintf("left = %d, mid = %d, right = %d\n", left, mid, right); + if ( !result ) + { + return (void*)data; + } + if ( result < 0 ) + { + left = mid + 1; + } + else + { + right = mid - 1; + } + } + return NULL; +} +static int CompareGameCodeAndVersion(const void* a, const void* b) +{ + return MI_CpuComp8(a, b, 5); +} + +/* +データベースを読み込む (前準備) +*/ +BOOL DHT_PrepareDatabase(DHTFile* pDHT) +{ + FSFile file; + u32 length; + s32 result; + SVCSignHeapContext pool; + u8 heap[4*1024]; + u8 md1[20]; + u8 md2[20]; + PROFILE_INIT(); + + // ファイルオープン + PROFILE_COUNT(); + if (!FS_OpenFileEx(&file, HASH_PATH, FS_FILEMODE_R)) + { + OS_TPrintf("Cannot open " HASH_PATH ".\n"); + return FALSE; + } + // ヘッダ読み込み + PROFILE_COUNT(); + result = FS_ReadFile(&file, &pDHT->header, sizeof(DHTHeader)); + if ( result != sizeof(DHTHeader) ) + { + OS_TPrintf("Cannot read the header of " HASH_PATH " (result=%d).\n", result); + return FALSE; + } + if ( pDHT->header.magic_code != DHT_MAGIC_CODE ) + { + OS_TPrintf("Invalid " HASH_PATH " magic code (magic=0x%08X).\n", pDHT->header.magic_code); + return FALSE; + } + // サイズチェック + PROFILE_COUNT(); + length = FS_GetFileLength(&file); + if ( length != sizeof(DHTHeader) + pDHT->header.nums * sizeof(DHTDatabase) ) + { + OS_TPrintf("Invalid " HASH_PATH " size (%d != %d).\n", length, sizeof(DHTHeader) + pDHT->header.nums * sizeof(DHTDatabase)); + return FALSE; + } + // databaseサイズの保存 + length = pDHT->header.nums * sizeof(DHTDatabase); + // データベース読み込み + PROFILE_COUNT(); + result = FS_ReadFile(&file, pDHT->database, (s32)length); + if ( result != length ) + { + OS_TPrintf("Cannot read the database of " HASH_PATH " (result=%d).\n", result); + return FALSE; + } + FS_CloseFile(&file); + // ファイル署名取り出し + PROFILE_COUNT(); + SVC_InitSignHeap(&pool, heap, sizeof(heap)); + SVC_DecryptSign(&pool, md1, pDHT->header.sign, &g_pubkey_DER[29]); + // ハッシュ計算 + PROFILE_COUNT(); + SVC_CalcSHA1(md2, DHT_GET_SIGN_TARGET_ADDR(&pDHT->header), DHT_GET_SIGN_TARGET_SIZE(&pDHT->header)); + // 検証 + PROFILE_COUNT(); + result = SVC_CompareSHA1(md1, md2); + if ( !result ) + { + OS_TPrintfEx("SIGN = % 20B\n", md1); + OS_TPrintfEx("HASH = % 20B\n", md2); + OS_TPrintf("Signature is not valid.\n"); + return FALSE; + } + // 結果報告 +#ifdef PRINT_PROFILE + PROFILE_COUNT(); + OS_TPrintf("\nDone to prepare the database.\n"); + OS_TPrintf("%10d msec for file open.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0])); + OS_TPrintf("%10d msec for reading header.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1])); + OS_TPrintf("%10d msec for size check.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2])); + OS_TPrintf("%10d msec for reading database.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3])); + OS_TPrintf("%10d msec for decrypt sign.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4])); + OS_TPrintf("%10d msec for hashing database.\n", (int)OS_TicksToMilliSeconds(profile[6]-profile[5])); + OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[7]-profile[6])); + OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[7]-profile[0])); +#endif + return TRUE; +} +/* +ROMヘッダに対応するデータベースを手に入れる +*/ +const DHTDatabase* DHT_GetDatabase(const DHTFile* pDHT, const ROM_Header_Short* pROMHeader) +{ + u8 data[5]; + DHTDatabase* db; + PROFILE_INIT(); + + // 準備 + PROFILE_COUNT(); + MI_CpuCopy8( pROMHeader->game_code, data, 4 ); + data[4] = pROMHeader->rom_version; + db = (DHTDatabase*)bsearch(data, pDHT->database, pDHT->header.nums, sizeof(DHTDatabase), CompareGameCodeAndVersion); + if ( !db ) + { + OS_TPrintf("Cannot find the database.\n"); + } +#ifdef PRINT_PROFILE + PROFILE_COUNT(); + OS_TPrintf("%10d msec for searching database.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0])); +#endif + return db; +} +/* +ハッシュ計算 (1) +読み込み済みデータをチェックする +*/ +BOOL DHT_CheckHashPhase1(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, const void* pARM9, const void* pARM7) +{ + SVCHMACSHA1Context ctx; + u8 md[20]; + BOOL result; + PROFILE_INIT(); + + // 準備 + PROFILE_COUNT(); + SVC_HMACSHA1Init(&ctx, hmac_key, sizeof(hmac_key)); + // ヘッダ + PROFILE_COUNT(); + SVC_HMACSHA1Update(&ctx, pROMHeader, DHT_DS_HEADER_SIZE); + // ARM9 Static + PROFILE_COUNT(); + SVC_HMACSHA1Update(&ctx, pARM9, pROMHeader->main_size); + // ARM7 Static + PROFILE_COUNT(); + SVC_HMACSHA1Update(&ctx, pARM7, pROMHeader->sub_size); + // 検証 + PROFILE_COUNT(); + SVC_HMACSHA1GetHash(&ctx, md); + result = SVC_CompareSHA1(db->hash[0], md); + if ( !result ) + { + OS_TPrintfEx("DB = % 20B\n", db->hash[0]); + OS_TPrintfEx("HASH = % 20B\n", md); + OS_TPrintf("%s: hash[0] is not valid.\n", __func__); + } + // 結果報告 +#ifdef PRINT_PROFILE + PROFILE_COUNT(); + OS_TPrintf("\nDone to check the hash (phase 1).\n"); + OS_TPrintf("%10d msec for preparing hash.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0])); + OS_TPrintf("%10d msec for scanning header.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1])); + OS_TPrintf("%10d msec for scanning ARM9.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2])); + OS_TPrintf("%10d msec for scanning ARM7.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3])); + OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4])); + OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[0])); +#endif + return result; +} +/* +ハッシュ計算 (2) +対象領域の読み込みとチェックを行う +FSを用いたテストの場合とCARDアプリの場合で異なる +*/ +#if 1 +// FS版 (fctx == FSFile*) +static BOOL ReadImage(void* fctx, void* dest, s32 offset, s32 length) +{ + FSFile* fp = fctx; + s32 result; + if ( !FS_SeekFile(fp, offset, FS_SEEK_SET) ) + { + OS_TPrintf("Cannot seek to the offset (%d bytes).\n", offset); + return FALSE; + } + result = FS_ReadFile(fp, dest, length); + if ( result != length ) + { + OS_TPrintf("Cannot read the data (%d bytes).\n", length); + return FALSE; + } + return TRUE; +} +#else +// CARD版 (fctx == dma no) +static BOOL ReadImage(void* fctx, void* dest, s32 offset, s32 length) +{ + u32 dma = (u32)fctx; + CARD_ReadRom(dma, (void*)offset, dest, (u32)length); + return TRUE; +} +#endif + +static BOOL ImageHMACSHA1Update(SVCHMACSHA1Context* ctx, void* fctx, s32 offset, s32 length, void* buffer) +{ + if ( !ReadImage(fctx, buffer, offset, length) ) + { + return FALSE; + } + SVC_HMACSHA1Update(ctx, buffer, (u32)length); + return TRUE; +} + +static BOOL GetOverlayInfo(int no, void* fctx, int fat_offset, int* pOffset, int* pLength) +{ + ROM_FAT fat; + if ( !ReadImage(fctx, &fat, fat_offset + no * (s32)sizeof(ROM_FAT), sizeof(ROM_FAT)) ) + { + return FALSE; + } + if ( pOffset ) + { + *pOffset = (s32)fat.top.offset; + } + if ( pLength ) + { + *pLength = (s32)(fat.bottom.offset - fat.top.offset); + } + return TRUE; +} + +BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* fctx, void* buffer) +{ + int overlay_nums = (int)(pROMHeader->main_ovt_size / sizeof(ROM_OVT)); + u8 md[20]; + PROFILE_INIT(); + + if ( overlay_nums ) + { + SVCHMACSHA1Context ctx; + int total_sectors; + int i; + + // 準備 + PROFILE_COUNT(); + SVC_HMACSHA1Init(&ctx, hmac_key, sizeof(hmac_key)); + // OVT + PROFILE_COUNT(); + if ( !ImageHMACSHA1Update(&ctx, fctx, (s32)pROMHeader->main_ovt_offset, (s32)pROMHeader->main_ovt_size, buffer) ) + { + OS_TPrintf("Cannot calc HMAC-SHA1 for OVT.\n"); + return FALSE; + } + // FAT + PROFILE_COUNT(); + if ( !ImageHMACSHA1Update(&ctx, fctx, (s32)pROMHeader->fat_offset, overlay_nums * (s32)sizeof(ROM_FAT), buffer) ) + { + OS_TPrintf("Cannot calc HMAC-SHA1 for %d of FAT.\n", overlay_nums); + return FALSE; + } + // 各オーバーレイ + PROFILE_COUNT(); + total_sectors = 0; + for (i = 0; i < overlay_nums; i++) + { + int max_sectors = (DHT_OVERLAY_MAX/512 - total_sectors) / (overlay_nums - i); + int offset; + int length; + if ( !GetOverlayInfo(i, fctx, (s32)pROMHeader->fat_offset, &offset, &length) ) + { + OS_TPrintf("Cannot get %d of overlay info.\n", i); + return FALSE; + } + length = (length + 511) / 512; // bytes -> sectors + if ( length > max_sectors ) + { + length = max_sectors; + } + if ( !ImageHMACSHA1Update(&ctx, fctx, offset, length * 512, buffer) ) + { + OS_TPrintf("Cannot calc HMAC-SHA1 for %d of overlay.\n", i); + return FALSE; + } + total_sectors += length; + } + // 検証 + PROFILE_COUNT(); + SVC_HMACSHA1GetHash(&ctx, md); + } + else + { + PROFILE_COUNT(); + PROFILE_COUNT(); + PROFILE_COUNT(); + PROFILE_COUNT(); + PROFILE_COUNT(); + MI_CpuClear8(md, sizeof(md)); + } + if ( !SVC_CompareSHA1(md, db->hash[1]) ) + { + OS_TPrintfEx("DB = % 20B\n", db->hash[1]); + OS_TPrintfEx("HASH = % 20B\n", md); + OS_TPrintf("%s: hash[1] is not valid.\n", __func__); + return FALSE; + } + // 結果報告 +#ifdef PRINT_PROFILE + PROFILE_COUNT(); + OS_TPrintf("\nDone to check the hash (phase 2).\n"); + OS_TPrintf("%10d msec for preparing hash.\n", (int)OS_TicksToMilliSeconds(profile[1]-profile[0])); + OS_TPrintf("%10d msec for scanning OVT.\n", (int)OS_TicksToMilliSeconds(profile[2]-profile[1])); + OS_TPrintf("%10d msec for scanning FAT.\n", (int)OS_TicksToMilliSeconds(profile[3]-profile[2])); + OS_TPrintf("%10d msec for scanning every overlays.\n", (int)OS_TicksToMilliSeconds(profile[4]-profile[3])); + OS_TPrintf("%10d msec for comparing hash.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[4])); + OS_TPrintf("\nTotal: %10d msec.\n", (int)OS_TicksToMilliSeconds(profile[5]-profile[0])); +#endif + return TRUE; +} + + diff --git a/build/tests/CheckDSHashTable/src/main.c b/build/tests/CheckDSHashTable/src/main.c new file mode 100644 index 00000000..2194d15b --- /dev/null +++ b/build/tests/CheckDSHashTable/src/main.c @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - tests - CheckDSHashTable + File: main.c + + Copyright 2008 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ + +#include +#include + +/* + このサンプルはテスト用であり、CARD関数の代わりにFS関数で + DHTライブラリが実装されている前提である +*/ + +#define ROM_PATH "/srl" + +#define DS_HASH_TABLE_NUMS 3000 +#define DS_HASH_TABLE_SIZE (sizeof(DHTHeader) + DS_HASH_TABLE_NUMS * sizeof(DHTDatabase)) + +/* + DHTファイル読み込み先 +*/ +static u8 dht_buffer[DS_HASH_TABLE_SIZE] ATTRIBUTE_ALIGN(32); +static DHTFile *const dht = (DHTFile*)dht_buffer; +/* + Phase2用バッファ +*/ +static u8 ov_buffer[DHT_OVERLAY_MAX]; + +/* + 実際にはアドレス固定 +*/ +#include +static ROM_Header_Short rom_header ATTRIBUTE_ALIGN(32); // 使うのは DHT_DS_HEADER_SIZE だけ +static u8 rom_arm9[3*1024*1024] ATTRIBUTE_ALIGN(32); +static u8 rom_arm7[1024*1024] ATTRIBUTE_ALIGN(32); +#include + + +static void VBlankIntr( void ) +{ + OS_SetIrqCheckFlag(OS_IE_V_BLANK); +} + +/* + 検証本番のうち、実際にはオーバーヘッドにならない処理 +*/ +static BOOL CheckValidation(FSFile* fp) +{ + const DHTDatabase *db; + s32 result; + + // ヘッダの読み込み + result = FS_ReadFile(fp, &rom_header, DHT_DS_HEADER_SIZE); + if ( result != DHT_DS_HEADER_SIZE ) + { + OS_TPrintf("Cannot read ROM header.\n"); + return FALSE; + } + // ARM9部分 + if ( rom_header.main_size > sizeof(rom_arm9) ) + { + OS_TPrintf("Too large main size (%d > %d).\n", rom_header.main_size, sizeof(rom_arm9)); + return FALSE; + } + if ( !FS_SeekFile(fp, (s32)rom_header.main_rom_offset, FS_SEEK_SET) ) + { + OS_TPrintf("Cannot seek to ARM9 static.\n"); + return FALSE; + } + result = FS_ReadFile(fp, rom_arm9, (s32)rom_header.main_size); + if ( result != rom_header.main_size ) + { + OS_TPrintf("Cannot read ARM9 static.\n"); + return FALSE; + } + // ARM7部分 + if ( rom_header.sub_size > sizeof(rom_arm7) ) + { + OS_TPrintf("Too large sub size (%d > %d).\n", rom_header.sub_size, sizeof(rom_arm7)); + return FALSE; + } + if ( !FS_SeekFile(fp, (s32)rom_header.sub_rom_offset, FS_SEEK_SET) ) + { + OS_TPrintf("Cannot seek to ARM7 static.\n"); + return FALSE; + } + result = FS_ReadFile(fp, rom_arm7, (s32)rom_header.sub_size); + if ( result != rom_header.sub_size ) + { + OS_TPrintf("Cannot read ARM7 static.\n"); + return FALSE; + } + + // データベースの検索 + db = DHT_GetDatabase(dht, &rom_header); + if ( !db ) + { + return FALSE; + } +//OS_TPrintf("FOUND: 0x%08X: %.4s(%d)\n", db, db->game_code, db->rom_version); + // ハッシュ計算 (1) - 隠蔽可能なはず + if ( !DHT_CheckHashPhase1(db, &rom_header, rom_arm9, rom_arm7) ) + { + return FALSE; + } + // ハッシュ計算 (2) - 隠蔽は難しいか + if ( !DHT_CheckHashPhase2(db, &rom_header, fp, ov_buffer) ) + { + return FALSE; + } + + return TRUE; +} + +void TwlMain(void) +{ + OS_Init(); + OS_InitTick(); + + (void)OS_EnableIrq(); + (void)OS_EnableInterrupts(); + + // 割り込み許可---------------------------- + (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr); + (void)OS_EnableIrqMask(OS_IE_V_BLANK); + (void)GX_VBlankIntr(TRUE); + + FS_Init(FS_DMA_NOT_USE); + + // 署名ロード + if ( !DHT_PrepareDatabase(dht) ) + { + OS_TPanic("Cannot prepare the database.\n"); + } + + // 本番 + { + FSFile dir; + FSDirectoryEntryInfo info; + BOOL result; + result = FS_OpenDirectory(&dir, ROM_PATH, FS_FILEMODE_R); + if ( !result ) + { + OS_TPanic("Cannot open " ROM_PATH ".\n"); + } + while ( FS_ReadDirectory(&dir, &info) ) + { + FSFile file; + OSTick begin; + char path[FS_ENTRY_LONGNAME_MAX+sizeof(ROM_PATH)+1]; + if ( info.attributes & FS_ATTRIBUTE_IS_DIRECTORY ) + { + OS_TPrintf("%s is directory.\n", info.longname); + continue; + } + STD_CopyString(path, ROM_PATH "/"); + STD_ConcatenateString(path, info.longname); + if (!FS_OpenFileEx(&file, path, FS_FILEMODE_R)) + { + OS_TPrintf("Cannot open %s.\n", path); + continue; + } + OS_TPrintf("\nTrying %s...\n", path); + begin = OS_GetTick(); + if ( !CheckValidation(&file) ) + { + OS_TPrintf("Failed. %d msec (includes loading static data).\n", (int)OS_TicksToMilliSeconds(OS_GetTick()-begin)); + } + else + { + OS_TPrintf("Success. %d msec (includes loading static data).\n", (int)OS_TicksToMilliSeconds(OS_GetTick()-begin)); + } + FS_CloseFile(&file); + } + FS_CloseDirectory(&dir); + } + + OS_TPrintf("\nDone.\n"); + OS_Terminate(); +} + diff --git a/include/sysmenu/dht/dht.h b/include/sysmenu/dht/dht.h new file mode 100644 index 00000000..db5dbb97 --- /dev/null +++ b/include/sysmenu/dht/dht.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - DHT + File: dht.h + + Copyright 2008 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: $ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef SYSMENU_DHT_H_ +#define SYSMENU_DHT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + Name: DHT_PrepareDatabase + + Description: 全データベースを読み込む + + Arguments: pDHT 全データベースの格納先 + + Returns: 成功すればTRUE + *---------------------------------------------------------------------------*/ +BOOL DHT_PrepareDatabase(DHTFile* pDHT); + +/*---------------------------------------------------------------------------* + Name: DHT_GetDatabase + + Description: ROMヘッダに対応するデータベースを検索する + + Arguments: pDHT 全データベースの格納先 + pROMHeader 対象となるROMヘッダ格納先 + + Returns: 対象データベースへのポインタ + *---------------------------------------------------------------------------*/ +const DHTDatabase* DHT_GetDatabase(const DHTFile* pDHT, const ROM_Header_Short* pROMHeader); + +/*---------------------------------------------------------------------------* + Name: DHT_CheckHashPhase1 + + Description: ROMヘッダおよびARM9/ARM7スタティック領域の検証 + + Arguments: db 対象データベースへのポインタ + pROMHeader 対象となるROMヘッダ格納先 + pARM9 対象となるARM9スタティック格納先 + pARM7 対象となるARM7スタティック格納先 + + Returns: 問題なければTRUE + *---------------------------------------------------------------------------*/ +BOOL DHT_CheckHashPhase1(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, const void* pARM9, const void* pARM7); + +/*---------------------------------------------------------------------------* + Name: DHT_CheckHashPhase2 + + Description: オー馬齢領域の検証 + + Arguments: db 対象データベースへのポインタ + pROMHeader 対象となるROMヘッダ格納先 + fctx (FS版) FSFile構造体へのポインタ + (CARD版) dma番号をvoid*にキャストしたもの + buffer 本APIで使用するワーク (DHT_OVERLAY_MAXだけ必要) + + Returns: 問題なければTRUE + *---------------------------------------------------------------------------*/ +BOOL DHT_CheckHashPhase2(const DHTDatabase *db, const ROM_Header_Short* pROMHeader, void* fctx, void* buffer); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // SYSMENU_DHT_H_ diff --git a/include/sysmenu/dht/dht_format.h b/include/sysmenu/dht/dht_format.h new file mode 100644 index 00000000..b41f957b --- /dev/null +++ b/include/sysmenu/dht/dht_format.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------* + Project: TwlIPL - DHT + File: dht_format.h + + Copyright 2008 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + $Date:: 2007-09-06$ + $Rev$ + $Author$ + *---------------------------------------------------------------------------*/ +#ifndef SYSMENU_DHT_FORMAT_H_ +#define SYSMENU_DHT_FORMAT_H_ + +#define DHT_MAGIC_CODE (('N' << 0)|('D' << 8)|('H' << 16)|('T' << 24)) +#define DHT_DS_HEADER_SIZE 0x160 +#define DHT_OVERLAY_MAX (512*1024) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DHTHeader +{ + u32 magic_code; // fixed + u8 sign[128]; // for nums member and whole DHTDatabase array + u32 nums; // number of subsequent DHTDatabase array +} +DHTHeader; + +typedef struct DHTDatabase +{ + u8 game_code[4]; + u8 rom_version; + u8 reserved[3]; // for 4B alignment DHTDatabase array + u8 hash[2][20]; +} +DHTDatabase; + +typedef struct DHTFile +{ + DHTHeader header; + DHTDatabase database[]; +} +DHTFile; + +#define DHT_HMAC_KEY { \ + 0x61, 0xbd, 0xdd, 0x72, 0x7e, 0x72, 0xbe, 0xde, 0xad, 0x3a, 0xdf, 0x7f, 0x3d, 0x2d, 0xf7, 0xa5, \ + 0x16, 0x7e, 0xb4, 0xc9, 0x7c, 0x6c, 0x00, 0x7c, 0x57, 0xbb, 0x94, 0x8a, 0x64, 0xcd, 0x4e, 0x1c, \ + 0x51, 0x6b, 0xbd, 0xdb, 0x1d, 0xeb, 0x54, 0xe9, 0x34, 0x27, 0xf9, 0x31, 0x51, 0x5e, 0x89, 0x4e, \ + 0x7f, 0xd9, 0x7c, 0xe9, 0x92, 0x44, 0x0f, 0xef, 0x6b, 0xb6, 0x12, 0x21, 0x68, 0x88, 0xd8, 0xee \ +} + + +/* + ユーティリティ + hp: メモリ上のファイルの先頭アドレス +*/ +#define DHT_GET_SIGN_TARGET_ADDR(hp) (&((DHTHeader*)hp)->nums) +#define DHT_GET_SIGN_TARGET_SIZE(hp) (((DHTHeader*)hp)->nums * sizeof(DHTDatabase) + sizeof(u32)) + +#define DHT_GET_SIGN_TARGET_OFFSET (int)DHT_GET_SIGN_TARGET_ADDR(0) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif //SYSMENU_DHT_FORMAT_H_