バナーが存在しないNTRソフトの予約領域に無理矢理バナーを挿入する裏ツールを追加。

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@325 7061adef-622a-194b-ae81-725974e89856
This commit is contained in:
nishikawa_takeshi 2009-06-26 08:35:52 +00:00
parent cb5f80b08d
commit 3844fbfd8b
3 changed files with 846 additions and 0 deletions

View File

@ -0,0 +1,214 @@
@echo off
rem
rem mastering & comparing sample batch file
rem
rem Simple usage: SRLファイルをドラッグすると
rem %output_dir%にマスタリング結果を出力し、正しくできたか検証を行う
rem TADの場合にはCLS用のフォルダを構成する
rem
rem 補足: %~d0%~p0はバッチファイルのパスです
rem 補足: %~d1%~p1は各入力ファイルのパスです
rem
rem -------------------------------------------------------
rem 動作モード
rem -------------------------------------------------------
rem light_mode [YES/NO]
rem 簡易版処理にするかどうか
rem 簡易版のとき出力フォルダを作成せず、SRLのマスタリングまでで処理を終了する
set light_mode="NO"
rem -------------------------------------------------------
rem 引数チェック
rem -------------------------------------------------------
set usage=USAGE: %~nx0 INPUT_FILE...
if ""%1"" == """" (
echo %usage%
echo 使用方法が間違っています。
echo マスタリング前のSRL/TADをドラッグアンドドロップしてください。
echo.
goto end
)
rem -------------------------------------------------------
rem プログラムのパス設定
rem -------------------------------------------------------
set tooldir=%~d0%~p0\bin\
set banner_insert_tool=%tooldir%BannerForcefulInserter.exe
set banner_template_file=%tooldir%default.bnr
set analyzer_tool=%tooldir%SrlAnalyzer.TWL.exe
set this_bat=%~dpnx0
rem -------------------------------------------------------
rem ループ開始 (%0を使うのはここまで、%1を使うのはここから、%2以降は使わない)
rem -------------------------------------------------------
:begin
rem プログラム確認
if not exist "%banner_insert_tool%" (
echo mastering tool "%banner_insert_tool%" is not found.
goto end
)
if not exist "%banner_template_file%" (
echo comparing tool "%banner_template_file%" is not found.
goto end
)
if not exist "%analyzer_tool%" (
echo srl analyzer tool "%analyzer_tool%" is not found.
goto end
)
rem -------------------------------------------------------
rem 入出力ファイルのパス設定
rem -------------------------------------------------------
rem 入力パス
set input_rom=%~dpnx1
set input_rom_short=%~nx1
set input_ext=%~x1
if not exist "%input_rom%" (
echo %input_rom% is not found.
goto end
)
rem 出力パス
set output_banner_srl_short=%~n1.banner.srl
set output_dir=%~d1%~p1%~n1.master.out\
if %light_mode%=="YES" (
set output_dir=%~d1%~p1%\
)
set output_parent_dir=%~d1%~p1\
set output_banner_srl=%output_dir%%output_banner_srl_short%
set output_readme=%output_dir%Readme.txt
set output_log=%output_dir%log.txt
rem 出力フォルダの作成
if not exist "%output_dir%" (
mkdir "%output_dir%"
)
rem これ以降 %1を使わない
set input_srl=%input_rom%
rem -------------------------------------------------------
rem 出力フォルダに ログファイル を作成する
rem -------------------------------------------------------
rem ログファイルはすでに存在していたとき追記していく
echo =================================================>>"%output_log%"
echo [作成日時] %datetmp% %timetmp%>>"%output_log%"
echo [作成元] %this_bat%>>"%output_log%"
echo =================================================>>"%output_log%"
rem -------------------------------------------------------
rem 出力フォルダに Readme を作成する
rem -------------------------------------------------------
echo =================================================>>"%output_readme%"
echo 結果の説明>>"%output_readme%"
echo =================================================>>"%output_readme%"
echo [作成日時] %datetmp% %timetmp%>>"%output_readme%"
echo [作成元] %this_bat%>>"%output_readme%"
echo.>>"%output_readme%"
rem -------------------------------------------------------
rem 入力ファイルのパラメータを取得しておく
rem -------------------------------------------------------
set tmpprog="%analyzer_tool%" "%input_srl%" -p
for /F "delims=" %%a in ('"%tmpprog%"') do set platform=%%a
set tmpprog="%banner_insert_tool%" "%input_srl%" "%output_banner_srl%" "%banner_template_file%" -c
for /F "delims=" %%a in ('"%tmpprog%"') do set isbannerexist=%%a
rem -------------------------------------------------------
rem バナーを無理矢理挿入する
rem -------------------------------------------------------
if "%platform%"=="NTR" (
if "%isbannerexist%"=="NOTEXIST" (
echo.
echo.
echo ****************************************************************
echo * *
echo * *
echo * バナーが存在しないのでバナーを無理矢理挿入します。 *
echo * *
echo * *
echo ****************************************************************
echo.
echo.
echo [注意] バナーが存在しないのでバナーを無理矢理挿入しました。>>"%output_log%"
echo.>>"%output_readme%"
echo ------------------------------------------>>"%output_readme%"
echo 注意>>"%output_readme%"
echo ------------------------------------------>>"%output_readme%"
echo バナーが存在しないのでバナーを無理矢理挿入しました。>>"%output_readme%"
echo.>>"%output_readme%"
"%banner_insert_tool%" "%input_srl%" "%output_banner_srl%" "%banner_template_file%"
set input_srl=%output_banner_srl%
) else (
echo.
echo.
echo ****************************************************************
echo * *
echo * *
echo * バナーが存在するのでバナーを挿入する必要はありません。 *
echo * *
echo * *
echo ****************************************************************
echo.
echo.
echo [注意] バナーが存在するのでバナーを挿入する必要はありません。>>"%output_log%"
echo.>>"%output_readme%"
echo ------------------------------------------>>"%output_readme%"
echo 注意>>"%output_readme%"
echo ------------------------------------------>>"%output_readme%"
echo バナーが存在するのでバナーを挿入する必要はありません。>>"%output_readme%"
echo.>>"%output_readme%"
)
)
rem -------------------------------------------------------
rem 入力ファイルが残っているならbeginに戻る
rem -------------------------------------------------------
:mastering_end
echo 以上>>"%output_readme%"
echo.
echo ================================================================================================
echo %input_rom_short% のバナーつけかえが終了しました。
echo.
echo 出力ファイルは %output_dir% に作成されました。
echo 詳細はフォルダ内の Readme.txt をご覧ください。
echo エラーや警告がある場合フォルダ内の log.txt に記述されます。
echo ================================================================================================
echo.
shift
if ""%1"" neq """" goto begin
rem -------------------------------------------------------
rem 終了 (キー入力待ち)
rem -------------------------------------------------------
:end
echo.
echo すべてのマスタリングが終了しました。
pause

View File

@ -0,0 +1,80 @@
#! make -f
#---------------------------------------------------------------------------
# Project: TwlSDK - tools - mastering.TWL
# File: Makefile.TWL
#
# 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$
#---------------------------------------------------------------------------
TARGET_PLATFORM = TWL
include $(TWLSDK_ROOT)/build/buildtools/commondefs
TARGETS = BannerForcefulInserter.exe
SOURCES_C = main.c ../MenuSkipFlagTool/keys.c
SOURCES = $(SOURCES_C)
OBJECTS = $(SOURCES:.c=.o)
INCDIR = $(TWLSDK_ROOT)/build/tools/makerom.TWL \
$(TWL_IPL_RED_ROOT)/include \
../MenuSKipFlagTool
REVISION_H = revision.h
#INSTALL_DIR = $(FIRM_INSTALL_TOOLSDIR)/bin
#INSTALL_TARGETS = $(TARGETS)
MACROS += $(addprefix -I,$(INCDIR)) -DPLATFORM_ENDIAN_LITTLE
LIBACSIGN = $(ROOT)/build/tools/makerom.TWL/acsign/lib/X86/libacsign_x86.a
LIBAES = $(ROOT)/build/tools/makerom.TWL/aes/lib/X86/libaes_x86.a
LIBDIGEST = $(ROOT)/build/tools/makerom.TWL/digest/lib/X86/libdigest_x86.a
#LIBDGT = $(ROOT)/build/tools/libdgt.TWL/lib/libdgt.TWL.a
LDIRT_CLEAN = $(OBJECTS) $(TARGETS) *.BAK $(REVISION_H)
include $(TWLSDK_ROOT)/build/buildtools/twl/modulerules.x86
#----------------------------------------------------------------------------
# build
#----------------------------------------------------------------------------
do-build: $(TARGETS)
$(TARGETS): $(REVISION_H) $(OBJECTS) $(LIBACSIGN) $(LIBAES) $(LIBDIGEST)
$(CC_X86) $+ -o $@ -lnetapi32 -lwsock32
main.o: main.c
#main.h:
# avoid to warning message
#misc.o:WARNING += -Wno-format-y2k
#
$(REVISION_H) ::
@if test -e $(TWLSDK_ROOT)/.svn; then \
LANG=C svn info $(call empath,$(TWLSDK_ROOT)) | grep 'Revision' | sed "s|Revision: \(.*\)|#define SDK_REVISION \"\1\"|" > $(REVISION_H); \
else \
echo "#define SDK_REVISION \"-\"" > $(REVISION_H); \
fi
@if test -e $(TWL_IPL_RED_ROOT)/.svn; then \
LANG=C svn info $(call empath,$(TWL_IPL_RED_ROOT)) | grep 'Revision' | sed "s|Revision: \(.*\)|#define IPL_REVISION \"\1\"|" >> $(REVISION_H); \
else \
echo "#define IPL_REVISION \"-\"" >> $(REVISION_H); \
fi
#test: path.c misc.c
# $(CC_X86) -DTEST $+ -o $@

View File

@ -0,0 +1,552 @@
/*---------------------------------------------------------------------------*
Project: TwlFirmware - tools - mastering
File: mastering.c
Copyright 2003 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 <stdio.h>
#include <stdlib.h>
#include <string.h> // strcasecmp()
#include <getopt.h> // getopt()
#include <sys/stat.h> // stat()
#include <stdarg.h>
#include <conio.h>
#include <twl/types.h>
#include <twl/os/common/format_rom.h>
#include <twl/os/common/ownerInfoEx.h>
#include <acsign/include/acsign.h>
#include "revision.h"
#include "keys.h"
/*---------------------------------------------------------------------------*
&
*---------------------------------------------------------------------------*/
// -- 内部パラメータ
// CRC (makerom.TWL/misc.cとmakerom.TWL/format_rom_private.hからコピペ)
#define CRC16_INIT_VALUE (0xffff)
#define CALC_CRC16_SIZE (0x15e)
// -- Context
typedef struct _SContext
{
// 入出力ファイル
FILE *ifp;
FILE *ofp;
FILE *banner_fp;
}
SContext;
// -- internal function
static BOOL iMain( SContext *pContext );
BOOL CopyFile( FILE *dst, FILE *src );
u16 CalcCRC16(u16 start, u8 *data, int size);
BOOL SignRomHeader( ROM_Header *prh );
BOOL DecryptSignRomHeader( ROM_Header *prh );
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
BOOL DebugMode = FALSE;
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
void usage()
{
printf( "-----------------------------------------------------------------------------\n" );
printf( "Usage: RatingAllFreeTool.exe input_file output_file banner_file\n" );
printf( " input_file : a ROM data file.\n" );
printf( " output_file : a destination file.\n" );
printf( " banner_file : a banner file.\n" );
printf( "\nOption:\n" );
printf( "-h : print help only.\n" );
printf( "-f : force to overwrite a output_file.\n" );
printf( "-c : check whether the banner exists in the input_file. [EXIST/NOTEXIST]\n" );
printf( "-----------------------------------------------------------------------------\n" );
}
int main(int argc, char *argv[])
{
SContext context;
char *pSrc, *pDst, *pBanner;
int opt;
extern char *optarg;
extern int optind, opterr;
struct stat st;
BOOL bResult = TRUE;
BOOL bForceOverwrite = FALSE;
BOOL bCheck = FALSE;
printf( "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" );
printf( " ManuSkipFlagTool [%s-%s]\n", SDK_REVISION, IPL_REVISION );
printf( "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" );
// context の初期化
memset( &context, 0, sizeof(SContext) );
// オプション
while( (opt = getopt(argc, argv, "hfc")) >= 0 )
{
switch( opt )
{
case 'h':
usage();
return 0;
break;
case 'f':
bForceOverwrite = TRUE;
break;
case 'c':
bCheck = TRUE;
break;
default: // オプション引数が指定されていないときにも実行される
usage();
fprintf( stdout, "\n*** Error: illegal option. ***\n" );
exit(1);
break;
}
}
argc = argc - optind;
argv = argv + optind;
// 引数処理
if( argc != 3 )
{
usage();
printf( "\n*** Error: Auguments. ***\n" );
return -1;
}
pSrc = argv[0];
pDst = argv[1];
pBanner = argv[2];
printf( "Auguments:\n" );
printf( " input_file : %s\n", pSrc );
printf( " output_file : %s\n", pDst );
printf( " banner_file : %s\n", pBanner );
printf( "--\n" );
// 入力ファイルと出力ファイル名が同じならダメ
if( (strlen(pSrc) == strlen(pDst)) && (memcmp(pSrc, pDst, strlen(pSrc)) == 0) )
{
printf( "\n*** Error: Same filename between the input_file and the output_file. ***\n" );
printf( "\n" );
printf( "error.\n" );
return -1;
}
// 出力ファイルが存在するとき上書きするかどうかを確認する
if( !bCheck && !bForceOverwrite && stat( pDst, &st )==0 )
{
char ans;
printf( "The %s already exists. Overwrite it? (y or n) ", pDst );
//fscanf( stdin, "%c", &ans );
ans = (char)getch(); // リターンキーなし
printf( "%c\n", ans ); // getch では入力が表示されないので自分で表示する必要あり
printf( "\n" );
if( !(ans=='y') && !(ans=='Y') )
{
printf( "\n" );
printf( "canceled.\n" );
return -1;
}
}
// チェックモード
if( bCheck )
{
FILE *fp = fopen(pSrc, "rb");
ROM_Header rh;
if( sizeof(ROM_Header) != fread( &rh, 1, sizeof(ROM_Header), fp) )
{
printf( "\n*** Error: Failed to read the ROM Header. ***\n" );
return -1;
}
// オフセットが設定されているときバナーが存在するとみなす
if( rh.s.banner_offset != 0 )
{
printf("EXIST");
}
else
{
printf("NOTEXIST");
}
return 0;
}
// ファイルを開く
context.ifp = fopen(pSrc, "rb");
context.ofp = fopen(pDst, "wb+");
context.banner_fp = fopen(pBanner, "rb");
if( !(context.ifp) || !(context.ofp) || !(context.banner_fp) )
{
printf( "\n*** Error: Failed to open the file. ***\n" );
bResult = FALSE;
goto FINALIZE;
}
// ファイルコピー
if( !CopyFile( context.ofp, context.ifp ) )
{
printf( "\n*** Error: Failed to copy the file. ***\n" );
bResult = FALSE;
goto FINALIZE;
}
// フラグ立てが指定されていないときはコピーだけしてそのまま終了
bResult = iMain( &context );
// 終了処理
FINALIZE:
if( !bResult )
{
printf( "\n" );
printf( "error.\n" );
}
else
{
printf( "\n" );
printf( "succeeded.\n" );
}
if( context.ifp ) fclose(context.ifp); // 資源の解放
if( context.ofp ) fclose(context.ofp);
if( (!bResult) && (stat( pDst, &st ) == 0) )
{
unlink( pDst ); // 出力ファイルを削除する
}
return ((bResult == TRUE)?0:-1); // 成功のとき0
}
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
static BOOL iMain( SContext *pContext )
{
ROM_Header rh;
int banner_size;
u8 *banner_buf;
u8 *tmp;
u16 curr_crc;
// ROMヘッダをリード
fseek( pContext->ifp, 0, SEEK_SET );
if( sizeof(ROM_Header) != fread( &rh, 1, sizeof(ROM_Header), pContext->ifp ) )
{
printf( "\n*** Error: Failed to read the ROM Header. ***\n" );
return FALSE;
}
// NTRのみ許可
if( rh.s.platform_code != PLATFORM_CODE_NTR )
{
printf("\n*** Error: Illegal platform (%d). ***\n", rh.s.platform_code);
return FALSE;
}
// バナーが存在するときダメ
if( rh.s.banner_offset != 0 )
{
printf("\n*** Error: The banner has already exists (offset = 0x%08X). ***\n", (unsigned int)rh.s.banner_offset);
return FALSE;
}
printf("InitialCode : %c%c%c%c\n", rh.s.game_code[0], rh.s.game_code[1], rh.s.game_code[2], rh.s.game_code[3]);
// バナーを読み込む
fseek(pContext->banner_fp, 0, SEEK_END);
banner_size = ftell(pContext->banner_fp);
banner_buf = (u8*)malloc(banner_size);
if( !banner_buf )
{
printf("\n*** Error: Failed to malloc. ***\n");
return FALSE;
}
fseek( pContext->banner_fp, 0, SEEK_SET );
if( banner_size != fread( banner_buf, 1, banner_size, pContext->banner_fp ) )
{
printf( "\n*** Error: Failed to read the Banner file. ***\n" );
free(banner_buf);
return FALSE;
}
// バナーをホワイトリストハッシュ以降の0x3C0からの領域に入れる(最大で0xDFFまでなので署名よりも前の領域に収まる)
tmp = (u8*)&rh;
memcpy( &tmp[0x3C0], banner_buf, banner_size );
rh.s.banner_offset = 0x3C0; // オフセットを上書き
free(banner_buf);
// ヘッダCRC計算
curr_crc = rh.s.header_crc16;
rh.s.header_crc16 = CalcCRC16( CRC16_INIT_VALUE, (u8*)&rh, CALC_CRC16_SIZE );
printf( "Header CRC : 0x%04X -> 0x%04X\n", curr_crc, rh.s.header_crc16 );
// ROMヘッダを上書き
fseek( pContext->ofp, 0, SEEK_SET );
if( sizeof(ROM_Header) != fwrite( &rh, 1, sizeof(ROM_Header), pContext->ofp ) )
{
printf( "\n*** Error: Failed to write the ROM Header. ***\n" );
return FALSE;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*/
// ファイルコピー用バッファ
#define BUFSIZE (16*1024)
BOOL CopyFile( FILE *dst, FILE *src )
{
static u8 buf[ BUFSIZE ];
int size;
fseek( src, 0, SEEK_END );
size = ftell( src );
fseek( src, 0, SEEK_SET );
fseek( dst, 0, SEEK_SET );
while( size > 0 )
{
int len = (BUFSIZE < size)?BUFSIZE:size;
if( len != fread( buf, 1, len, src ) )
{
printf( "\n*** Error! failed to read the file in copying. ***\n" );
return FALSE;
}
if( len != fwrite( buf, 1, len, dst ) )
{
printf( "\n*** Error! failed to write the file in copying. ***\n" );
return FALSE;
}
size -= len;
}
return TRUE;
}
/*---------------------------------------------------------------------------*
CRCの計算
*---------------------------------------------------------------------------*/
static u16 crc16_table[16] = {
0x0000, 0xCC01, 0xD801, 0x1400,
0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401,
0x5000, 0x9C01, 0x8801, 0x4400
};
u16 CalcCRC16(u16 start, u8 *data, int size)
{
u16 r1;
u16 total = start;
while (size-- > 0)
{
// 下位4bit
r1 = crc16_table[total & 0xf];
total = (total >> 4) & 0x0fff;
total = total ^ r1 ^ crc16_table[*data & 0xf];
// 上位4bit
r1 = crc16_table[total & 0xf];
total = (total >> 4) & 0x0fff;
total = total ^ r1 ^ crc16_table[(*data >> 4) & 0xf];
data++;
}
return total;
}
/*---------------------------------------------------------------------------*
ROMヘッダの署名 ()
*---------------------------------------------------------------------------*/
BOOL SignRomHeader( ROM_Header *prh )
{
SignatureData signSrc; // 署名のもととなるダイジェスト値
u8 signDst[ RSA_KEY_LENGTH ]; // 署名の格納先Tmpバッファ
u8 decryptBlock[ RSA_KEY_LENGTH ]; // 署名を解除後ブロックバッファ
BOOL result;
int pos;
const u8 *privatekey = NULL;
const u8 *publickey = NULL;
u8 *idL = prh->s.titleID_Lo;
u32 idH = prh->s.titleID_Hi;
// ROMヘッダのダイジェストを算出(先頭から証明書領域の直前までが対象)
ACSign_DigestUnit(
signSrc.digest,
prh,
(u32)&(prh->certificate) - (u32)prh
);
// 鍵選択
if( (idL[3]=='H') && (idL[2]=='N') && (idL[1]=='A') ) // ランチャアプリかどうかはTitleID_Loの値で決定
{
printf("Key type : Launcher\n");
privatekey = g_devPrivKey_DER_Launcher;
publickey = g_devPubKey_DER_Launcher;
}
else if( idH & TITLE_ID_HI_SECURE_FLAG_MASK ) // 各ビットは排他的とは限らないのでelse ifにはならない
{
printf("Key type : Secure\n");
privatekey = g_devPrivKey_DER_Secure;
publickey = g_devPubKey_DER_Secure;
}
else if( (idH & TITLE_ID_HI_APP_TYPE_MASK) == 1 )
{
printf("Key type : System\n");
privatekey = g_devPrivKey_DER_System;
publickey = g_devPubKey_DER_System;
}
else if( (idH & TITLE_ID_HI_APP_TYPE_MASK) == 0 )
{
printf("Key type : User\n");
privatekey = g_devPrivKey_DER_User;
publickey = g_devPubKey_DER_User;
}
if( !privatekey || !publickey )
{
printf( "\n*** Error: Illegal key. ***\n" );
return FALSE;
}
// ダイジェストに署名をかける
result = ACSign_Encrypto( signDst, privatekey, &signSrc, sizeof(SignatureData) );
if( !result )
{
printf( "\n*** Error: Failed to encrypt the signature. ***\n" );
return FALSE;
}
// 署名を解除してダイジェストと一致するかベリファイする
result = ACSign_Decrypto( decryptBlock, publickey, signDst, RSA_KEY_LENGTH );
for( pos=0; pos < RSA_KEY_LENGTH; pos++ )
{
if( decryptBlock[pos] == 0x0 ) // 解除後ブロックから実データをサーチ
break;
}
if( !result || (memcmp( &signSrc, &(decryptBlock[pos+1]), sizeof(SignatureData) ) != 0) )
{
printf( "\n*** Error: Failed to verify the signature. ***\n" );
return FALSE;
}
// ROMヘッダに署名を上書き
memcpy( prh->signature, signDst, RSA_KEY_LENGTH );
return TRUE;
} // ECSrlResult RCSrl::signRomHeader(void)
// 署名を外す
BOOL DecryptSignRomHeader( ROM_Header *prh )
{
u8 original[ RSA_KEY_LENGTH ]; // 署名外した後のデータ格納先
s32 pos = 0; // ブロックの先頭アドレス
u8 digest[ DIGEST_SIZE_SHA1 ]; // ROMヘッダのダイジェスト
const u8 *publickey = NULL;
u8 *idL = prh->s.titleID_Lo;
u32 idH = prh->s.titleID_Hi;
// <データの流れ>
// (1) 公開鍵で復号した結果(ブロック)をローカル変数(original)に格納
// (2) ブロックから余分な部分を取り除いて引数(pDst)にコピー
// 鍵選択
if( (idL[3]=='H') && (idL[2]=='N') && (idL[1]=='A') ) // ランチャアプリかどうかはTitleID_Loの値で決定
{
publickey = g_devPubKey_DER_Launcher;
}
else if( idH & TITLE_ID_HI_SECURE_FLAG_MASK ) // 各ビットは排他的とは限らないのでelse ifにはならない
{
publickey = g_devPubKey_DER_Secure;
}
else if( (idH & TITLE_ID_HI_APP_TYPE_MASK) == 1 )
{
publickey = g_devPubKey_DER_System;
}
else if( (idH & TITLE_ID_HI_APP_TYPE_MASK) == 0 )
{
publickey = g_devPubKey_DER_User;
}
if( !publickey )
{
printf( "\n*** Error: Illegal key. ***\n" );
return FALSE;
}
// 署名の解除 = 公開鍵で復号
if( !ACSign_Decrypto( original, publickey, prh->signature, RSA_KEY_LENGTH ) )
{
printf( "\n*** Error: Failed to decrypt the signature. ***\n" );
return FALSE;
}
// 署名前データを復号後ブロックからゲット
for( pos=0; pos < (RSA_KEY_LENGTH-2); pos++ ) // 本来ブロックの先頭は0x00だが復号化の内部処理によって消える仕様
{
// 暗号ブロック形式 = 0x00, BlockType, Padding, 0x00, 実データ
if( original[pos] == 0x00 ) // 実データの直前の0x00をサーチ
{
break;
}
}
// ベリファイ
// ROMヘッダのダイジェストを算出(先頭から証明書領域の直前までが対象)
ACSign_DigestUnit( digest, prh, (u32)&(prh->certificate) - (u32)prh );
if( memcmp( &(original[pos+1]), digest, DIGEST_SIZE_SHA1 ) != 0 )
{
return FALSE;
}
return TRUE;
}
// end of file