split_tad 移植版:関数をマスタエディタのフォルダに移して、こちらからは参照することにする。

git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@59 7061adef-622a-194b-ae81-725974e89856
This commit is contained in:
nishikawa_takeshi 2008-12-04 10:05:42 +00:00
parent 04f52448ee
commit 483f433a62
8 changed files with 5 additions and 589 deletions

View File

@ -1,275 +0,0 @@
#include "stdafx.h"
#include "twl/types.h"
#include <cstring>
#include <cstdio>
#include "split_tad.h"
#include "split_tad_util.h"
// ------------------------------------------------------
// 宣言と定数
// ------------------------------------------------------
// internal functions
cli::array<System::Byte>^ readTitleKey( cli::array<System::Byte> ^ticket );
cli::array<System::Byte>^ decCBC( cli::array<System::Byte> ^ Key, cli::array<System::Byte> ^ IV, cli::array<System::Byte> ^cipherText );
cli::array<rcContentsInfo^> ^readContentsInfo( cli::array<System::Byte> ^tmd );
// tad外し用の鍵
const u8 commonKey[] =
{
0xA1,0x60,0x4A,0x6A,0x71,0x23,0xB5,0x29,0xAE,0x8B,0xEC,0x32,0xC8,0x16,0xFC,0xAA
};
// ------------------------------------------------------
// tad外し処理本体
// ------------------------------------------------------
//
// tad ファイルから srl(0番目のコンテンツ)を抜き出す
// (split_tad_dev.pl の移植)
//
// @arg [in] 入力 tad ファイル名
// @arg [out] 出力 srl ファイル名
//
// @ret 成功したとき0 失敗したら負の値
//
int splitTad( System::String ^tadpath, System::String ^srlpath )
{
FILE *fp = NULL;
const char *pchFilename =
(const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( tadpath ).ToPointer();
if( fopen_s( &fp, pchFilename, "rb" ) != NULL )
{
return -1;
}
cli::array<System::Byte> ^mbuf = subStr( fp, 0, 32 );
u32 hdrSize = reverseEndian( unpack32(mbuf, 0) ); // 基本的にビッグエンディアン
u16 tadType = reverseEndian( unpack16(mbuf, 4) );
u16 tadVersion = reverseEndian( unpack16(mbuf, 6) );
u32 certSize = reverseEndian( unpack32(mbuf, 8) );
u32 crlSize = reverseEndian( unpack32(mbuf, 12) );
u32 ticketSize = reverseEndian( unpack32(mbuf, 16) );
u32 tmdSize = reverseEndian( unpack32(mbuf, 20) );
u32 contentSize = reverseEndian( unpack32(mbuf, 24) );
u32 metaSize = reverseEndian( unpack32(mbuf, 28) );
printf( "hdrSize %d\n", hdrSize );
printf( "tadType %c%c\n", tadType>>8, tadType&0xFF );
printf( "tadVersion %d\n", tadVersion );
printf( "certSize %d\n", certSize );
printf( "crlSize %d\n", crlSize );
printf( "ticketSize %d\n", ticketSize );
printf( "tmdSize %d\n", tmdSize );
printf( "contentSize %d\n", contentSize );
printf( "metaSize %d\n", metaSize );
u32 certOffset = roundUp( hdrSize, 64);
u32 crlOffset = roundUp( certOffset + certSize, 64);
u32 ticketOffset = roundUp( crlOffset + crlSize, 64);
u32 tmdOffset = roundUp( ticketOffset + ticketSize, 64);
u32 contentOffset = roundUp( tmdOffset + tmdSize, 64);
u32 metaOffset = roundUp( contentOffset + contentSize, 64);
u32 fileSize = roundUp( metaOffset + metaSize, 64);
fseek( fp, 0, SEEK_END );
u32 orgFileSize = ftell( fp );
if( fileSize != orgFileSize )
{
printf( "file size is not expected size(=%d)", fileSize );
fclose( fp );
return -1;
}
cli::array<System::Byte> ^ticket = subStr( fp, ticketOffset, ticketSize );
cli::array<System::Byte> ^tmd = subStr( fp, tmdOffset, tmdSize );
cli::array<System::Byte> ^content = subStr( fp, contentOffset, contentSize );
//saveFile( "cert.bin", subStr( fp, certOffset, certSize ) );
//saveFile( "crl.bin", subStr( fp, crlOffset, crlSize ) );
//saveFile( "ticket.bin", ticket );
//saveFile( "tmd.bin", tmd );
//saveFile( "meta.bin", subStr( fp, metaOffset, metaSize ) );
cli::array<System::Byte> ^title_key = readTitleKey( ticket );
cli::array<rcContentsInfo^> ^rci = readContentsInfo( tmd );
dumpBytes( title_key );
// 通常は tad は srl (コンテンツ No.0) しか含まないが
// マルチコンテンツ を含む場合のために No.1 以降も別ファイルとして保存する
// srl 名が out.srl のとき out_1.bin out_2.bin ... として出力する
System::String ^srl_dir = System::IO::Path::GetDirectoryName( srlpath ); // 格納ディレクトリ名
System::String ^srl_prefix = System::IO::Path::GetFileNameWithoutExtension( srlpath ); // 拡張子よりも前のファイル名
System::String ^srl_ext = System::IO::Path::GetExtension( srlpath ); // 拡張子
int result = 0;
u32 offset = 0;
for each( rcContentsInfo ^ci in rci )
{
u32 size = roundUp( (u32)ci->size, 16 );
cli::array<System::Byte> ^enc_content_x = subStr( content, offset, size );
cli::array<System::Byte> ^content_x_iv = resizeBytes( pack16( reverseEndian(ci->idx) ), 14 ); // ビッグエンディアンにしておく
cli::array<System::Byte> ^dec_content_x = decCBC( title_key, content_x_iv, enc_content_x );
cli::array<System::Byte> ^dec_content = subStr( dec_content_x, 0, ci->size );
System::Security::Cryptography::SHA1 ^sha1 = gcnew System::Security::Cryptography::SHA1Managed();
cli::array<System::Byte> ^hash = sha1->ComputeHash( dec_content );
dumpBytes( hash );
pin_ptr<unsigned char> calc = &hash[0]; // 計算で求めたハッシュ
pin_ptr<unsigned char> extr = &ci->hash[0]; // 抽出したハッシュ
if( memcmp( calc, extr, 20 ) == 0 )
{
printf( "hash OK\n" );
}
else
{
printf( "hash mismatch\n" );
result = -1; // エラーとする 中断はせず最後まで作成
}
//saveFile( "content_" + ci->idx.ToString() + ".encrypted.bin", enc_content_x );
//saveFile( "content_" + ci->idx.ToString() + ".bin", dec_content );
if( ci->idx == 0 )
{
saveFile( srlpath, dec_content ); // コンテンツ No.0 が srl にあたる
}
else
{
System::String ^tmppath = srl_dir + "\\" + srl_prefix + "_" + ci->idx.ToString() + ".bin";
saveFile( tmppath, dec_content );
}
offset += roundUp( size, 64 );
}
fclose( fp );
return result;
}
// ------------------------------------------------------
// internal functions
// ------------------------------------------------------
//
// title_key の復号
//
// @ret title_key のバイト列
//
cli::array<System::Byte>^ readTitleKey( cli::array<System::Byte> ^ticket )
{
cli::array<System::Byte> ^encTitleKey = subStr( ticket, 0x1BF, 16 );
cli::array<System::Byte> ^IV = resizeBytes( subStr( ticket, 0x1DC, 8 ), 8 ); // 16バイトに拡張してケツの8バイトを0で埋める
cli::array<System::Byte> ^comKey = gcnew cli::array<System::Byte>(16);
pin_ptr<unsigned char> pComKey = &comKey[0];
memcpy( pComKey, commonKey, 16 );
cli::array<System::Byte> ^plain;
try
{
plain = decCBC( comKey, IV, encTitleKey );
}
catch (System::Exception ^ e)
{
System::Console::WriteLine("Exception in readTitleKey(): {0}", e->Message);
}
return plain;
}
//
// tmd から各コンテンツファイルの情報を抜き出す
//
// @ret 各コンテンツファイルの情報をまとめた Array
//
cli::array<rcContentsInfo^> ^readContentsInfo( cli::array<System::Byte> ^tmd )
{
u16 nContent = reverseEndian( unpack16(tmd, 0x1DE) );
cli::array<rcContentsInfo^> ^ci = gcnew cli::array<rcContentsInfo^>( nContent );
u16 i;
for( i=0; i < nContent; i++ )
{
u32 offset = 0x1E4 + 36*i;
ci[i] = gcnew rcContentsInfo;
ci[i]->cid = reverseEndian( unpack32(tmd, offset) );
ci[i]->idx = reverseEndian( unpack16(tmd, offset + 4) );
ci[i]->type = reverseEndian( unpack16(tmd, offset + 6) );
ci[i]->size = reverseEndian( unpack32(tmd, offset + 12) );
ci[i]->hash = subStr( tmd, offset + 16, 20 );
}
return ci;
}
//
// AES復号 : System::Security::Cryptography::RijndaelManaged のヘルプのサンプルをコピペ
//
// @ret 復号後のデータ
//
cli::array<System::Byte>^ decCBC( cli::array<System::Byte> ^ Key, cli::array<System::Byte> ^ IV, cli::array<System::Byte> ^cipherText )
{
// Check arguments.
if (!cipherText || cipherText->Length <= 0)
throw gcnew System::ArgumentNullException("cipherText");
if (!Key || Key->Length <= 0)
throw gcnew System::ArgumentNullException("Key");
if (!IV || IV->Length <= 0)
throw gcnew System::ArgumentNullException("Key");
// TDeclare the streams used
// to decrypt to an in memory
// array of bytes.
System::IO::MemoryStream ^msDecrypt;
System::Security::Cryptography::CryptoStream ^csDecrypt;
// Declare the RijndaelManaged object
// used to decrypt the data.
System::Security::Cryptography::RijndaelManaged ^aesAlg;
// Declare the string used to hold
// the decrypted text.
cli::array<System::Byte> ^plain = gcnew cli::array<System::Byte>(cipherText->Length);
try
{
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = gcnew System::Security::Cryptography::RijndaelManaged();
aesAlg->Mode = System::Security::Cryptography::CipherMode::CBC; // CBCモード
aesAlg->Key = Key;
aesAlg->IV = IV;
aesAlg->Padding = System::Security::Cryptography::PaddingMode::Zeros;
// Create a decrytor to perform the stream transform.
System::Security::Cryptography::ICryptoTransform ^ decryptor
= aesAlg->CreateDecryptor(aesAlg->Key, aesAlg->IV);
// Create the streams used for decryption.
msDecrypt = gcnew System::IO::MemoryStream(cipherText);
csDecrypt = gcnew System::Security::Cryptography::CryptoStream
(msDecrypt, decryptor, System::Security::Cryptography::CryptoStreamMode::Read);
csDecrypt->Read( plain, 0, cipherText->Length );
//srDecrypt = gcnew System::IO::StreamReader(csDecrypt);
//// Read the decrypted bytes from the decrypting stream
//// and place them in a string.
//plaintext = srDecrypt->ReadToEnd();
}
finally
{
// Clean things up.
// Close the streams.
if (csDecrypt)
csDecrypt->Close();
if (msDecrypt)
msDecrypt->Close();
// Clear the RijndaelManaged object.
if (aesAlg)
aesAlg->Clear();
}
return plain;
}
// end of file

View File

@ -1,80 +0,0 @@
#pragma once
#include "twl/types.h"
#include <cstring>
#include <cstdio>
// ------------------------------------------------------
// APIs
// ------------------------------------------------------
//
// tad ファイルから srl(0番目のコンテンツ)を抜き出す
// (split_tad_dev.pl の移植)
//
// @arg [in] 入力 tad ファイルのパス
// @arg [out] 出力 srl ファイルのパス
//
// @ret 成功したとき0 失敗したら負の値
//
int splitTad( System::String ^tadpath, System::String ^srlpath );
// ------------------------------------------------------
// 内部処理用の構造体(プロトタイプ宣言できないのでヘッダに置く)
// ------------------------------------------------------
// コンテンツ情報の構造体
ref class rcContentsInfo
{
private:
System::UInt32 ^h_cid;
System::UInt16 ^h_idx;
System::UInt16 ^h_type;
System::UInt32 ^h_size;
cli::array<System::Byte> ^h_hash;
public:
rcContentsInfo()
{
this->h_cid = gcnew System::UInt32; // 解放の必要なし
this->h_idx = gcnew System::UInt16;
this->h_type = gcnew System::UInt16;
this->h_size = gcnew System::UInt32;
this->h_hash = gcnew cli::array<System::Byte>(20); // 固定長
}
public:
property System::UInt32 cid
{
void set( System::UInt32 v ){ *this->h_cid = v; };
System::UInt32 get(void){ return *this->h_cid; }
}
property System::UInt16 idx
{
void set( System::UInt16 v ){ *this->h_idx = v; };
System::UInt16 get(void){ return *this->h_idx; }
}
property System::UInt16 type
{
void set( System::UInt16 v ){ *this->h_type = v; };
System::UInt16 get(void){ return *this->h_type; }
}
property System::UInt32 size
{
void set( System::UInt32 v ){ *this->h_size = v; };
System::UInt32 get(void){ return *this->h_size; }
}
property cli::array<System::Byte> ^hash
{
void set( cli::array<System::Byte> ^h )
{
cli::array<System::Byte>::Copy( h, this->h_hash, 20 );
}
cli::array<System::Byte> ^get(void)
{
cli::array<System::Byte> ^cp = gcnew cli::array<System::Byte>(20); // コピーを返す
cli::array<System::Byte>::Copy( this->h_hash, cp, 20 );
return cp;
}
}
};

View File

@ -42,7 +42,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="C:\twlsdk\build\tools\makerom.TWL;C:\twlsdk\include"
AdditionalIncludeDirectories="&quot;C:\Documents and Settings\nishikawa_takeshi\My Documents\Visual Studio 2008\Projects\MasterEditorTWL\MasterEditorTWL&quot;;C:\twlsdk\build\tools\makerom.TWL;C:\twlsdk\include"
PreprocessorDefinitions="WIN32;_DEBUG"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
@ -188,7 +188,7 @@
>
</File>
<File
RelativePath=".\split_tad.cpp"
RelativePath="..\..\MasterEditorTWL\MasterEditorTWL\split_tad.cpp"
>
</File>
<File
@ -196,7 +196,7 @@
>
</File>
<File
RelativePath=".\split_tad_util.cpp"
RelativePath="..\..\MasterEditorTWL\MasterEditorTWL\split_tad_util.cpp"
>
</File>
<File
@ -230,11 +230,11 @@
>
</File>
<File
RelativePath=".\split_tad.h"
RelativePath="..\..\MasterEditorTWL\MasterEditorTWL\split_tad.h"
>
</File>
<File
RelativePath=".\split_tad_util.h"
RelativePath="..\..\MasterEditorTWL\MasterEditorTWL\split_tad_util.h"
>
</File>
<File

View File

@ -1,149 +0,0 @@
#include "stdafx.h"
#include "twl/types.h"
#include <cstring>
#include <cstdio>
#include "split_tad_util.h"
// ファイルから部分バイト列を抜き出す
cli::array<System::Byte>^ subStr( FILE *fp, const int offset, const int size )
{
if( size <= 0 )
{
return nullptr;
}
cli::array<System::Byte> ^mbuf = gcnew cli::array<System::Byte>(size); // メモリ解放の必要なし
pin_ptr<unsigned char> buf = &mbuf[0]; // fread が unmanaged 配列を引数にするので変換
(void)fseek( fp, offset, SEEK_SET );
if( fread( buf, 1, size, fp ) != size )
{
return nullptr;
}
return mbuf; // managed のほうを返す
}
// バイト列から部分バイト列を抜き出す
cli::array<System::Byte>^ subStr( cli::array<System::Byte> ^bytes, const int offset, const int size )
{
cli::array<System::Byte> ^sub = gcnew cli::array<System::Byte>(size);
cli::array<System::Byte>::Copy( bytes, offset, sub, 0, size );
return sub;
}
// ファイルを作成してバイト列を格納する
int saveFp( FILE *fp, cli::array<System::Byte> ^bytes )
{
if( bytes == nullptr )
{
return 0; // 空のファイルをつくりたいということなので正常終了とみなす
}
pin_ptr<unsigned char> tmp = &bytes[0]; // array型はふつうの配列ではないのでバイト配列に変換
int size = bytes->Length;
if( fwrite( tmp, 1, size, fp ) != size )
{
return -1;
}
return 0;
}
int saveFile( System::String ^filename, cli::array<System::Byte> ^bytes )
{
FILE *fp = NULL;
const char *pchFilename =
(const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( filename ).ToPointer();
// ファイルにROMヘッダをライト
if( fopen_s( &fp, pchFilename, "wb" ) != NULL ) // 同名ファイルを削除して新規にライト・バイナリ
{
return -1;
}
fseek( fp, 0, SEEK_SET );
int r = saveFp( fp, bytes );
fclose( fp );
return r;
}
// エンディアンを逆転させる(tadはビッグエンディアンなのであったほうが便利)
u32 reverseEndian( const u32 v )
{
u32 ret = (v<<24) | ((v<<8) & 0x00FF0000) | ((v>>8) & 0x0000FF00) | (v>>24);
return ret;
}
u16 reverseEndian( const u16 v )
{
u16 ret = (v<<8) | (v>>8);
return ret;
}
// 多バイト値をバイト列に変換(リトルエンディアン) *** perlのpackを意識 ***
cli::array<System::Byte> ^pack32( u32 v )
{
cli::array<System::Byte> ^bytes = gcnew cli::array<System::Byte>(4);
bytes[0] = v & 0xFF;
bytes[1] = (v >> 8) & 0xFF;
bytes[2] = (v >> 16) & 0xFF;
bytes[3] = (v >> 24) & 0xFF;
return bytes;
}
cli::array<System::Byte> ^pack16( u16 v )
{
cli::array<System::Byte> ^bytes = gcnew cli::array<System::Byte>(2);
bytes[0] = v & 0xFF;
bytes[1] = v >>8;
return bytes;
}
// バイト列の部分バイト列から多バイト値として解釈(リトルエンディアン) *** perlのunpackを意識 ***
u32 unpack32( cli::array<System::Byte> ^bytes, const int index )
{
pin_ptr<unsigned char> tmp = &bytes[0];
u32 v = (u32)*((u32*)(tmp+index));
return v;
}
u16 unpack16( cli::array<System::Byte> ^bytes, const int index )
{
pin_ptr<unsigned char> tmp = &bytes[0];
u16 v = (u16)*((u16*)(tmp+index));
return v;
}
// 丸める
u32 roundUp( const u32 v, const u32 align )
{
u32 r = ((v + align - 1) / align) * align;
return r;
}
u16 roundUp( const u16 v, const u16 align )
{
u16 r = ((v + align - 1) / align) * align;
return r;
}
// バイト列の長さを拡張して末尾を0で埋める
// (0x12345678 => 0x1234567800000000)
cli::array<System::Byte> ^resizeBytes( cli::array<System::Byte> ^org, const int difSize )
{
cli::array<System::Byte> ^r = gcnew cli::array<System::Byte>( org->Length + difSize );
cli::array<System::Byte>::Copy( org, 0, r, 0, org->Length );
return r;
}
// バイト列を16進で表示
void dumpBytes( cli::array<System::Byte> ^bytes )
{
for each( System::Byte b in bytes )
{
printf( "%02x", b );
}
printf( "\n" );
}
// end of file

View File

@ -1,80 +0,0 @@
#pragma once
#include "twl/types.h"
#include <cstring>
#include <cstdio>
// ------------------------------------------------------
// APIs
// ------------------------------------------------------
//
// ファイルから部分バイト列を抜き出す
//
// @ret 抜き出したバイト列
//
cli::array<System::Byte>^ subStr( FILE *fp, const int offset, const int size );
//
// バイト列から部分バイト列を抜き出す
//
// @ret 抜き出したバイト列
//
cli::array<System::Byte>^ subStr( cli::array<System::Byte> ^bytes, const int offset, const int size );
//
// ファイルを作成してバイト列を格納する
//
// @ret 成功したら0 失敗したら負の値
//
int saveFp( FILE *fp, cli::array<System::Byte> ^bytes );
int saveFile( System::String ^filename, cli::array<System::Byte> ^bytes );
//
// エンディアンを逆転させる(tadはビッグエンディアンなのであったほうが便利)
//
// @ret エンディアン逆転後の値
//
u32 reverseEndian( const u32 v );
u16 reverseEndian( const u16 v );
//
// 多バイト値をバイト列に変換(リトルエンディアン) *** perlのpackを意識 ***
//
// @ret 変換後のバイト列
//
cli::array<System::Byte> ^pack32( u32 v );
cli::array<System::Byte> ^pack16( u16 v );
//
// バイト列の部分バイト列から多バイト値として解釈(リトルエンディアン) *** perlのunpackを意識 ***
//
// @arg [in] バイト列
// @arg [in] 何バイト目からを多バイト値とみなすか
//
// @ret 解釈した後の多バイト値
//
u32 unpack32( cli::array<System::Byte> ^bytes, const int index );
u16 unpack16( cli::array<System::Byte> ^bytes, const int index );
//
// 丸める
//
u32 roundUp( const u32 v, const u32 align );
u16 roundUp( const u16 v, const u16 align );
//
// バイト列の長さを拡張して末尾を0で埋める
// (0x12345678 => 0x1234567800000000)
//
// @arg [in] 拡張前のバイト列
// @arg [in] 何バイト拡張するか(拡張分だけを指定 例えば4バイトを5バイトにする場合には1を指定)
//
// @ret 拡張後のバイト列(新たなバイト列を内部で生成)
//
cli::array<System::Byte> ^resizeBytes( cli::array<System::Byte> ^org, const int difSize );
// バイト列を16進で表示
void dumpBytes( cli::array<System::Byte> ^bytes );