diff --git a/build/libraries_sysmenu/sysmenu/ARM9/src/title.c b/build/libraries_sysmenu/sysmenu/ARM9/src/title.c index f30d60af..246f80a8 100644 --- a/build/libraries_sysmenu/sysmenu/ARM9/src/title.c +++ b/build/libraries_sysmenu/sysmenu/ARM9/src/title.c @@ -569,7 +569,7 @@ OS_TPrintf("RebootSystem failed: cant seek file(%d)\n", source[i]); #ifdef LOAD_APP_VIA_WRAM OS_TPrintf("RebootSystem : Load VIA WRAM %d.\n", i); - // [TODO:]ここで同時にハッシュ計算やAES処理もやってしまう予定 + // [TODO:]ここで同時にAES処理もやってしまう予定 // 別スレッドで同じWRAM使おうとすると多分コケるので注意 // コールバック関数に与える引数を初期化してRead diff --git a/build/libraries_sysmenu/sysmenu/common/src/decodeAES.c b/build/libraries_sysmenu/sysmenu/common/src/decodeAES.c index 1f7dd484..902a1754 100644 --- a/build/libraries_sysmenu/sysmenu/common/src/decodeAES.c +++ b/build/libraries_sysmenu/sysmenu/common/src/decodeAES.c @@ -20,15 +20,166 @@ #include // define data----------------------------------------------------------------- +#define PXI_FIFO_DATA_DECRYPTAES_W_INIT 0 +#define PXI_FIFO_DATA_DECRYPTAES_W_TARGET1 1 +#define PXI_FIFO_DATA_DECRYPTAES_W_TARGET2 2 +#define PXI_FIFO_DATA_DECRYPTAES_NORMAL 3 // extern data----------------------------------------------------------------- // function's prototype------------------------------------------------------- // global variable------------------------------------------------------------- // static variable------------------------------------------------------------- +#ifdef SDK_ARM9 static BOOL s_finished = FALSE; +void *s_Addr_AESregion[2]; +u32 s_Size_AESregion[2]; +BOOL s_initialized = FALSE; +#endif // const data------------------------------------------------------------------ #ifdef SDK_ARM9 +// WRAM経由ファイル読み込みのコールバックで使うAESデクリプト処理の初期化 +BOOL SYSM_InitDecryptAESRegion_W( ROM_Header_Short *hs ) +{ + // AESデクリプト領域アドレスの算出と保存 + // ヘッダ情報から、AESデクリプトが必要な領域のアドレスとサイズ + // (最終的な配置ではなく、ランチャーによってアプリがメモリにロードされた状態でのアドレス) + // を算出、保存する + // ここで保存したアドレスを使って、順次読み込んだ領域と比較しながらデクリプト処理を行う + // カードにも対応する場合、セキュア領域の退避についても考慮する必要あり + // ついでに7側に飛んで、鍵やらIDのセットも済ませておく + void *region_addr[2]; + u32 region_size[2]; + u32 region_offset[2]; + u32 module_offset[4]; + u32 module_size[4]; + void *module_addr[4]; + int l, m; + + // AES有効? + if( !hs->enable_aes ) + { + OS_TPrintf( "SYSM_InitDecryptAESRegion(arm9):AES disabled.\n" ); + s_initialized = FALSE; + return FALSE; + } + + module_offset[0] = hs->main_rom_offset; + module_offset[1] = hs->sub_rom_offset; + module_offset[2] = hs->main_ltd_rom_offset; + module_offset[3] = hs->sub_ltd_rom_offset; + module_size[0] = hs->main_size; + module_size[1] = hs->sub_size; + module_size[2] = hs->main_ltd_size; + module_size[3] = hs->sub_ltd_size; + module_addr[0] = hs->main_ram_address; + module_addr[1] = hs->sub_ram_address; + module_addr[2] = hs->main_ltd_ram_address; + module_addr[3] = hs->sub_ltd_ram_address; + + // 再配置情報があれば、モジュールは再配置情報のsrcのアドレスに格納されている + for( l=0; lromRelocateInfo[l].src != NULL ) + { + module_addr[l] = (void *)SYSMi_GetWork()->romRelocateInfo[l].src; + } + } + + // デクリプト情報算出&格納処理 + region_offset[0] = hs->aes_target_rom_offset; + region_offset[1] = hs->aes_target2_rom_offset; + region_size[0] = hs->aes_target_size; + region_size[1] = hs->aes_target2_size; + s_Addr_AESregion[0] = NULL; + s_Addr_AESregion[1] = NULL; + for( m=0; m<2; m++ ) + { + // デクリプトする暗号化領域の判定とオフセット計算(ARM9flx, ARM9ltd, ARM7flx, ARM7ltdのどれか) + region_addr[m] = NULL; + if( region_size[m] == 0 ) + { + continue; + } + for( l=0; l<4; l++ ) + { + // モジュール配置先の領域(サイズは32バイト単位に補正)に、復号指定領域が含まれているか? + if( module_offset[l] <= region_offset[m] && + region_offset[m] + region_size[m] <= module_offset[l] + MATH_ROUNDUP( module_size[l], SYSM_ALIGNMENT_LOAD_MODULE ) ) + { + region_addr[m] = (void *)( (u32)module_addr[l] + (region_offset[m] - module_offset[l]) ); + break; + } + } + if( region_addr[m] == NULL ) + { + continue; + } + + // Workに暗号化領域情報を格納 + s_Addr_AESregion[m] = region_addr[m]; + s_Size_AESregion[m] = region_size[m]; + } + + if(region_addr[0] == NULL && region_addr[1] == NULL) + { + // ターゲット1も2も存在しないor設定オフセットがおかしい + OS_TPrintf( "SYSM_InitDecryptAESRegion(arm9):No targets.\n" ); + s_initialized = FALSE; + return FALSE; + } + + // Workに開発/製品情報を格納 + SYSMi_GetWork()->isDeveloperAESMode = ( hs->developer_encrypt ? TRUE : FALSE ); + + // Workに「鍵」or「シードとゲームコード」をセット + if( hs->developer_encrypt ) + { + MI_CpuCopy8( hs->title_name, SYSMi_GetWork()->keyAES, AES_KEY_SIZE ); + }else + { + MI_CpuCopy8( hs->main_ltd_static_digest, SYSMi_GetWork()->seedAES, AES_KEY_SIZE ); + MI_CpuCopy8( hs->game_code, SYSMi_GetWork()->idAES, GAME_CODE_MAX ); + } + + // ARM7に開始通知 + s_finished = FALSE; + while( PXI_SendWordByFifo(PXI_FIFO_TAG_DECRYPTAES, PXI_FIFO_DATA_DECRYPTAES_W_INIT, FALSE) != PXI_FIFO_SUCCESS ) + { + OS_TPrintf( "SYSM_InitDecryptAESRegion(arm9):ARM9 PXI send error.\n" ); + } + + // ARM7からの完了通知を受け取って完了 + while( !s_finished ) + { + OS_WaitAnyIrq(); + } + + OS_TPrintf( "SYSM_InitDecryptAESRegion(arm9):Init finished.\n" ); + s_initialized = TRUE; + return TRUE; +} + +// WRAM経由ファイル読み込みのコールバックで使うAESデクリプト処理関数 +void SYSM_StartDecryptAESRegion_W( void *wram_addr, void *orig_addr, u32 size ) +{ +#pragma unused(wram_addr) +#pragma unused(orig_addr) +#pragma unused(size) + // [TODO:] + // AESデクリプト領域と、ファイルからWRAMに読み込んできた領域の目的地の比較 + // 共通部分となる領域のアドレスとサイズ(WRAMでのアドレス)をWORKに記録し、7で該当領域をデクリプトしてもらう + // 対象となる領域をデクリプトする際に必要なカウンタの値も算出してWORKに入れておく + // 一応、デクリプトする領域のキャッシュもケアしておく + // ついでにtarget1なのか2なのかもFIFOで送ると良いかも + if( !s_initialized ) + { + return; + } + +} + +// べた書きAESデクリプト処理 void SYSM_StartDecryptAESRegion( ROM_Header_Short *hs ) { void *region_addr[2]; @@ -132,7 +283,7 @@ void SYSM_StartDecryptAESRegion( ROM_Header_Short *hs ) // ARM7に開始通知 s_finished = FALSE; - while( PXI_SendWordByFifo(PXI_FIFO_TAG_DECRYPTAES, 0, FALSE) != PXI_FIFO_SUCCESS ) + while( PXI_SendWordByFifo(PXI_FIFO_TAG_DECRYPTAES, PXI_FIFO_DATA_DECRYPTAES_NORMAL, FALSE) != PXI_FIFO_SUCCESS ) { OS_TPrintf( "SYSM_StartDecryptAESRegion(arm9):ARM9 PXI send error.\n" ); } @@ -173,20 +324,8 @@ static void ReplaceWithAes( void* ptr, u32 size ) AES_Unlock(); } -#endif //ifdef SDK_ARM9 - -static void SYSMi_CallbackDecryptAESRegion(PXIFifoTag tag, u32 data, BOOL err) +static void SYSMi_SetKeys( void ) { -#pragma unused(tag) -#pragma unused(data) -#pragma unused(err) - -#ifdef SDK_ARM9 - s_finished = TRUE; -#else //SDK_ARM7 - int l; - - // 製品ならIDセット if ( !SYSMi_GetWork()->isDeveloperAESMode ) { AESi_InitKeysForApp( SYSMi_GetWork()->idAES ); @@ -204,23 +343,49 @@ static void SYSMi_CallbackDecryptAESRegion(PXIFifoTag tag, u32 data, BOOL err) AES_SetKeySeedA( (AESKeySeed*)SYSMi_GetWork()->seedAES ); } AES_Unlock(); - - for( l=0; l<2; l++ ) - { - if( SYSMi_GetWork()->addr_AESregion[l]==NULL ) - { - OS_TPrintf( "SYSM_StartDecryptAESRegion(arm7):Region %d skip.\n", (l+1) ); - continue; +} + +static void SYSMi_DecryptAESRegion_sub( int target ) +{ + if( SYSMi_GetWork()->addr_AESregion[target]==NULL ) + { + OS_TPrintf( "SYSMi_DecryptAESRegion_sub(arm7):Target Addr Error!\n" ); + return; + } + + // カウンタの初期値セット + MI_CpuCopy8( SYSMi_GetWork()->counterAES[target], &aesCounter, AES_BLOCK_SIZE ); + + // 鍵ロードして暗号化領域の復号開始 + ReplaceWithAes( SYSMi_GetWork()->addr_AESregion[target], SYSMi_GetWork()->size_AESregion[target] ); +} + +#endif //ifdef SDK_ARM9 + +static void SYSMi_CallbackDecryptAESRegion(PXIFifoTag tag, u32 data, BOOL err) +{ +#pragma unused(tag) +#pragma unused(data) +#pragma unused(err) + +#ifdef SDK_ARM9 + s_finished = TRUE; +#else //SDK_ARM7 + if(data == PXI_FIFO_DATA_DECRYPTAES_W_INIT) + { + SYSMi_SetKeys(); + }else if(data == PXI_FIFO_DATA_DECRYPTAES_W_TARGET1 || data == PXI_FIFO_DATA_DECRYPTAES_W_TARGET2) + { + int target = (int)(data - PXI_FIFO_DATA_DECRYPTAES_W_TARGET1); + SYSMi_DecryptAESRegion_sub( target ); + }else if(data == PXI_FIFO_DATA_DECRYPTAES_NORMAL) + { + int l; + SYSMi_SetKeys(); + for( l=0; l<2; l++ ) + { + SYSMi_DecryptAESRegion_sub( l ); } - - // カウンタの初期値セット - MI_CpuCopy8( SYSMi_GetWork()->counterAES[l], &aesCounter, AES_BLOCK_SIZE ); - - // 鍵ロードして暗号化領域の復号開始 - ReplaceWithAes( SYSMi_GetWork()->addr_AESregion[l], SYSMi_GetWork()->size_AESregion[l] ); - OS_TPrintf( "SYSM_StartDecryptAESRegion(arm7):Region %d decryption finished.\n", (l+1) ); - // DMA転送なのでARM9のためのキャッシュフラッシュは不要のはず - // もうARM7側でも再配置まで触らないのでキャッシュ破棄する必要もないはず } // ARM9に完了通知 diff --git a/include/sysmenu/sysmenu_lib/common/sysmenu_api.h b/include/sysmenu/sysmenu_lib/common/sysmenu_api.h index 2191e51b..3688cbed 100644 --- a/include/sysmenu/sysmenu_lib/common/sysmenu_api.h +++ b/include/sysmenu/sysmenu_lib/common/sysmenu_api.h @@ -102,7 +102,11 @@ extern BOOL SYSM_IsLoadTitleFinished( void ); // SYSM_StartLoadTitle extern void SYSM_StartAuthenticateTitle( TitleProperty *pBootTitle ); // 指定したTitlePropertyを別スレッドで検証開始 extern BOOL SYSM_IsAuthenticateTitleFinished( void ); // SYSM_StartAuthenticateTitleで起動したスレッドが終了したかどうかを確認 extern AuthResult SYSM_TryToBootTitle( TitleProperty *pBootTitle ); // pBootTitleで指定したタイトルをブート。成功時は、never return. + +// AES領域デクリプト extern void SYSM_StartDecryptAESRegion( ROM_Header_Short *hs ); // 起動するROMのAES暗号化領域のデクリプト開始 +extern BOOL SYSM_InitDecryptAESRegion_W( ROM_Header_Short *hs ); // WRAM経由ファイル読み込みのコールバックで使うAESデクリプト処理の初期化 +extern void SYSM_StartDecryptAESRegion_W( void *wram_addr, void *orig_addr, u32 size ); // WRAM経由ファイル読み込みのコールバックで使うAESデクリプト処理関数 // デバイス制御 extern void SYSM_CaribrateTP( void ); // タッチパネルキャリブレーション