TwlToolsRED/build/tools/MasterEditor/FingerPrinterTWL/FingerPrinterTWL/fingerprinter_util.cpp
nishikawa_takeshi a796e33f0f フィンガープリントプログラム:GUI版完成。tad対応。
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@259 7061adef-622a-194b-ae81-725974e89856
2009-04-16 10:52:14 +00:00

477 lines
13 KiB
C++

#include "stdafx.h"
#include <apptype.h>
#include <twl/types.h>
#include <twl/os/common/format_rom.h>
#include <acsign/include/acsign.h>
#include <cstring>
#include <cstdio>
#include <MasterEditorTWL/keys.h>
using namespace MasterEditorTWL;
// ----------------------------------------------------------------------
// ファイル処理
// ----------------------------------------------------------------------
// ファイル全体の読み込み
cli::array<System::Byte>^ ReadBin( System::String ^path )
{
System::IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( path );
const char *pch = (const char*)ptr.ToPointer();
FILE *fp = NULL;
System::Exception ^ex = nullptr;
cli::array<System::Byte> ^bin = nullptr;
try
{
if( fopen_s( &fp, pch, "rb" ) != NULL )
{
ex = gcnew System::Exception( "Fail to open file:" + path );
throw ex;
}
// ファイルサイズ分のメモリ割り当て
fseek( fp, 0, SEEK_END );
int size = ftell(fp);
bin = gcnew cli::array<System::Byte>(size);
pin_ptr<unsigned char> pbin = &bin[0];
fseek( fp, 0, SEEK_SET );
if( fread( (void*)pbin, 1, size, fp ) != size )
{
ex = gcnew System::Exception( "Fail to read data from " + path );
throw ex;
}
}
finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr );
if( fp ) fclose(fp);
if( ex )
{
throw ex;
}
}
return bin;
}
// ファイル全体のライト
void WriteBin( System::String ^path, cli::array<System::Byte> ^bin )
{
System::IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( path );
const char *pch = (const char*)ptr.ToPointer();
FILE *fp = NULL;
System::Exception ^ex = nullptr;
try
{
if( fopen_s( &fp, pch, "w+b" ) != NULL ) // 上書き・バイナリ
{
ex = gcnew System::Exception( "Fail to open file:" + path );
throw ex;
}
int size = bin->Length;
pin_ptr<unsigned char> pbin = &bin[0];
(void)fseek( fp, 0, SEEK_SET );
if( fwrite( (const void*)pbin, 1, size, fp ) != size )
{
ex = gcnew System::Exception( "Fail to write data to " + path );
throw ex;
}
}
finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr );
if( fp ) fclose( fp );
if( ex )
{
throw ex;
}
}
}
// ROMヘッダのリード
void ReadRomHeader( System::String ^srlpath, ROM_Header *dstrh )
{
System::IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( srlpath );
const char *pchFile = (const char*)ptr.ToPointer();
FILE *fp = NULL;
System::Exception ^ex = nullptr;
try
{
if( fopen_s( &fp, pchFile, "rb" ) != NULL )
{
ex = gcnew System::Exception( "Fail to open file:" + srlpath );
throw ex;
}
fseek( fp, 0, SEEK_SET );
if( fread( (void*)dstrh, 1, sizeof(ROM_Header), fp ) != sizeof(ROM_Header) )
{
ex = gcnew System::Exception( "Fail to read data from " + srlpath );
throw ex;
}
}
finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr );
if( fp ) fclose(fp);
if( ex )
{
throw ex;
}
}
}
// ROMヘッダのライト
void WriteRomHeader( System::String ^srlpath, ROM_Header *srcrh )
{
System::IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( srlpath );
const char *pchFile = (const char*)ptr.ToPointer();
FILE *fp = NULL;
System::Exception ^ex = nullptr;
try
{
if( fopen_s( &fp, pchFile, "r+b" ) != NULL ) // 上書き・バイナリ
{
ex = gcnew System::Exception( "Fail to open file:" + srlpath );
throw ex;
}
(void)fseek( fp, 0, SEEK_SET );
if( fwrite( (const void*)srcrh, 1, sizeof(ROM_Header), fp ) != sizeof(ROM_Header) )
{
ex = gcnew System::Exception( "Fail to write data to " + srlpath );
throw ex;
}
}
finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal( ptr );
if( fp ) fclose( fp );
if( ex )
{
throw ex;
}
}
}
// バイナリからのROMヘッダの抽出
void ExtractRomHeader( cli::array<System::Byte> ^bin, ROM_Header *dstrh )
{
int size = bin->Length;
pin_ptr<unsigned char> pbin = &bin[0];
if( size < sizeof(ROM_Header) )
{
throw gcnew System::Exception( "The binary size is less than size of the ROM Header." );
}
memcpy( dstrh, pbin, sizeof(ROM_Header) );
}
// バイナリへのROMヘッダの上書き
void OverwriteRomHeader( cli::array<System::Byte> ^bin, ROM_Header *srcrh )
{
int size = bin->Length;
pin_ptr<unsigned char> pbin = &bin[0];
if( size < sizeof(ROM_Header) )
{
throw gcnew System::Exception( "The binary size is less than size of the ROM Header." );
}
memcpy( pbin, srcrh, sizeof(ROM_Header) );
}
// ファイルコピー
#define COPY_FILE_BUFSIZE (10*1024*1024)
void CopyFile( System::String ^srcpath, System::String ^dstpath )
{
System::IntPtr srcptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( srcpath );
System::IntPtr dstptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( dstpath );
const char *pchSrcFile = (const char*)srcptr.ToPointer();
const char *pchDstFile = (const char*)dstptr.ToPointer();
FILE *ifp = NULL;
FILE *ofp = NULL;
System::Exception ^ex = nullptr;
try
{
if( fopen_s( &ifp, pchSrcFile, "rb" ) != NULL )
{
ex = gcnew System::Exception( "Fail to open file:" + srcpath );
throw ex;
}
if( fopen_s( &ofp, pchDstFile, "wb" ) != NULL ) // 同名ファイルを削除して新規にライト・バイナリ
{
ex = gcnew System::Exception( "Fail to open file:" + dstpath );
throw ex;
}
// 入力ファイルのサイズ取得
fseek( ifp, 0, SEEK_END );
System::Int32 size = ftell(ifp);
cli::array<System::Byte> ^mbuf = gcnew cli::array<System::Byte>(COPY_FILE_BUFSIZE); // 解放の必要なし
pin_ptr<unsigned char> buf = &mbuf[0];
fseek( ifp, 0, SEEK_SET );
fseek( ofp, 0, SEEK_SET );
while( size > 0 )
{
System::Int32 datasize = (COPY_FILE_BUFSIZE < size)?COPY_FILE_BUFSIZE:size;
if( datasize != fread(buf, 1, datasize, ifp) )
{
ex = gcnew System::Exception( "Fail to read data from " + srcpath );
throw ex;
}
if( datasize != fwrite(buf, 1, datasize, ofp) )
{
ex = gcnew System::Exception( "Fail to write data to " + dstpath );
throw ex;
}
size -= datasize;
}
}
finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal( srcptr );
System::Runtime::InteropServices::Marshal::FreeHGlobal( dstptr );
if( ifp ) fclose(ifp);
if( ofp ) fclose(ofp);
if( ex )
{
throw ex;
}
}
}
// ----------------------------------------------------------------------
// 署名
// ----------------------------------------------------------------------
// ROMヘッダに署名をつける
void SignRomHeader( ROM_Header *rh )
{
SignatureData signSrc; // 署名のもととなるダイジェスト値
u8 signDst[ RSA_KEY_LENGTH ]; // 署名の格納先Tmpバッファ
u8 decryptBlock[ RSA_KEY_LENGTH ]; // 署名を解除後ブロックバッファ
BOOL result = false;
int pos;
u8 *privateKey = (u8*)g_devPrivKey_DER;
u8 *publicKey = (u8*)g_devPubKey_DER;
// ROMヘッダのダイジェストを算出(先頭から証明書領域の直前までが対象)
ACSign_DigestUnit(
signSrc.digest,
rh,
(u32)&(rh->certificate) - (u32)rh // this->pRomHeader はマネージヒープ上にあるので実アドレスを取得できない
);
// 鍵を選ぶ
#ifdef METWL_VER_APPTYPE_LAUNCHER
if( this->IsAppLauncher )
{
privateKey = (u8*)g_devPrivKey_DER_launcher;
publicKey = (u8*)g_devPubKey_DER_launcher;
}
else
#endif //METWL_VER_APPTYPE_LAUNCHER
#ifdef METWL_VER_APPTYPE_SECURE
if( this->IsAppSecure )
{
privateKey = (u8*)g_devPrivKey_DER_secure;
publicKey = (u8*)g_devPubKey_DER_secure;
}
else
#endif //METWL_VER_APPTYPE_SECURE
#ifdef METWL_VER_APPTYPE_SYSTEM
if( this->IsAppSystem )
{
privateKey = (u8*)g_devPrivKey_DER_system;
publicKey = (u8*)g_devPubKey_DER_system;
}
else
#endif //METWL_VER_APPTYPE_SYSTEM
#ifdef METWL_VER_APPTYPE_USER
{
privateKey = (u8*)g_devPrivKey_DER;
publicKey = (u8*)g_devPubKey_DER;
}
#endif //METWL_VER_APPTYPE_USER
// ダイジェストに署名をかける
result = ACSign_Encrypto( signDst, privateKey, &signSrc, sizeof(SignatureData) );
if( !result )
{
throw gcnew System::Exception( "Exception: Fail to calc the hash of the ROM header." );
}
// 署名を解除してダイジェストと一致するかベリファイする
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) )
{
throw gcnew System::Exception( "Exception: Fail to compare the hash of the ROM header." );
}
// ROMヘッダに署名を上書き
memcpy( rh->signature, signDst, RSA_KEY_LENGTH );
} // ECSrlResult RCSrl::signRomHeader(void)
// ----------------------------------------------------------------------
// 変換
// ----------------------------------------------------------------------
// 文字列をバイト配列に変換
cli::array<System::Byte>^ TransStringToBytes( System::String ^src, const int len )
{
cli::array<System::Byte> ^bytes = gcnew cli::array<System::Byte>(len);
int i;
for( i=0; i < len; i++ )
{
bytes[i] = 0;
}
int j=0;
for( i=0; i < src->Length; i++ )
{
if( (src[i] != ' ') && (j < len) )
{
bytes[j++] = (System::Byte)src[i];
}
}
return bytes;
}
// 16進文字列をバイト配列に変換
cli::array<System::Byte>^ TransHexStringToBytes( System::String ^src, const int len )
{
cli::array<System::Byte> ^bytes = gcnew cli::array<System::Byte>(len);
int i;
for( i=0; i < len; i++ )
{
bytes[i] = 0;
}
int j=0;
for( i=0; i < src->Length; )
{
if( src[i] == ' ' )
{
i++;
continue;
}
if( (src[i] != ' ') && (j < len) )
{
bytes[j++] = System::Byte::Parse(src->Substring(i,2), System::Globalization::NumberStyles::HexNumber);
i += 2;
}
}
return bytes;
}
// バイト配列を16進文字列に変換
System::String^ TransBytesToHexString( cli::array<System::Byte> ^bytes )
{
System::String ^str = gcnew System::String("");
int i;
for( i=0; i < bytes->Length; i++ )
{
System::Byte b = bytes[i];
str += System::String::Format( "{0:X02}", (char)b );
str += " ";
}
return str;
}
// ----------------------------------------------------------------------
// GUI
// ----------------------------------------------------------------------
// ファイルをダイアログで取得
// @arg [in] デフォルトのディレクトリ
// @arg [in] 拡張子フィルタ
// @ret 取得したファイル名 エラーのとき nullptr
System::String^ OpenFileUsingDialog( System::String ^defdir, System::String ^filter )
{
System::Windows::Forms::OpenFileDialog ^dlg = gcnew (System::Windows::Forms::OpenFileDialog);
if( System::String::IsNullOrEmpty( defdir ) || !System::IO::Directory::Exists( defdir ) )
{
dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );
}
else
{
dlg->InitialDirectory = defdir; // 前に選んだディレクトリをデフォルトにする
}
dlg->Filter = filter;
dlg->FilterIndex = 1;
dlg->RestoreDirectory = true;
if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK )
{
return nullptr;
}
return System::String::Copy(dlg->FileName);
}
// セーブするファイルをダイアログで取得
// @arg [in] デフォルトのディレクトリ
// @arg [in] 拡張子フィルタ
// @arg [in] ファイルの拡張子が不正なときに追加するときの正しい拡張子
// @ret 取得したファイル名 エラーのとき nullptr
System::String^ SaveFileUsingDialog( System::String ^defdir, System::String ^filter, System::String ^extension )
{
System::String ^retfile;
System::Windows::Forms::SaveFileDialog ^dlg = gcnew (System::Windows::Forms::SaveFileDialog);
if( System::String::IsNullOrEmpty( defdir ) || !System::IO::Directory::Exists( defdir ) )
{
dlg->InitialDirectory = System::Environment::GetFolderPath( System::Environment::SpecialFolder::Desktop );
}
else
{
dlg->InitialDirectory = defdir;
}
dlg->Filter = filter;
dlg->FilterIndex = 1;
dlg->RestoreDirectory = true;
if( dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK )
{
return nullptr;
}
retfile = dlg->FileName;
if( !System::String::IsNullOrEmpty(extension) && !(dlg->FileName->ToLower()->EndsWith( extension->ToLower() )) )
{
retfile += extension;
}
return retfile;
}
// ----------------------------------------------------------------------
// 外部プログラムの実行
// ----------------------------------------------------------------------
// maketadの実行
// @arg [in] maketadのパス
// @arg [in] 入力SRLのパス
// @arg [in] 出力SRLのパス
void makeTad( System::String ^maketad_path, System::String ^srlpath, System::String ^tadpath )
{
System::Diagnostics::Process::Start( maketad_path, "\"" + srlpath + "\" -o \"" + tadpath + "\"" );
}