ctr_Repair/trunk/CardSaveDataMover/Imp/source/main.cpp

419 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: Horizon
File: main.cpp
Copyright (C)2009 Nintendo Co., Ltd. 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.
$Rev$
*---------------------------------------------------------------------------*/
#include <nn.h>
#include <nn/fs.h>
#include <nn/cfg/CTR/cfg_ApiSys.h>
#include <nn/cfg/CTR/cfg_ApiInit.h>
#include <nn/am/am_ApiLocalImporter.h>
#include <nn/am/am_ApiSystemMenu.h>
#include <nn/applet.h>
#include <nn/ndm.h>
#include <nn/crypto/crypto_RsaKey.h>
#include <nn/ps/ctr/ps_Api.h>
#include <stdio.h>
#include <string.h>
#include "demo.h"
#include "../common/ver.h"
#include "../common/sleep.h"
#include "../common/common.h"
#include "../common/shfnt.h"
#include "test_data.h"
#define INF_FILE "sdmc:/csm_inf.txt"
#define KEY_LENGTH 2048
#define LIST_FILE "sdmc:/csm_list.txt"
#define SIGN_FILE "sdmc:/csm_sign.dat"
//#define PUBK_FILE "sdmc:/csm_key_public.der"
#define PRVK_FILE "sdmc:/csm_key_private.der"
extern "C" {
extern u8* PUBLIC_KEY_BEGIN[];
extern u8* PUBLIC_KEY_END[];
const void* PUBLIC_KEY = PUBLIC_KEY_BEGIN;
}
demo::RenderSystemDrawing s_RenderSystem;
nn::fnd::ExpHeap appHeap;
uptr heapForGx;
namespace
{
u8* readBuf;
}
bool ImportFile(nn::fs::MediaType mediaType, wchar_t* filename)
{
nn::Result result;
nn::fs::FileOutputStream* stream;
result = nn::am::BeginImportProgram(&stream, mediaType);
if (result.IsSuccess())
{
//NN_LOG("Importing: %ls...", filename);
nn::fs::FileInputStream in(filename);
while(s32 read = in.Read(readBuf, sizeof(readBuf)))
{
stream->Write(readBuf, read);
}
result = nn::am::EndImportProgram(stream);
}
return result.IsSuccess();
}
#define LIST_MAX 4000
u8 s_list[LIST_MAX][nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1] NN_ATTRIBUTE_ALIGN(32);//シリアルリスト
u8 sign[256] NN_ATTRIBUTE_ALIGN(32);//署名
//u8 key[1024*10] NN_ATTRIBUTE_ALIGN(32);//署名
u8 serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1];
bool GetSerial(){
nn::cfg::CTR::init::Initialize();
nn::cfg::CTR::system::Initialize();
nn::Result result = nn::cfg::CTR::system::GetSerialNo(serialNo);
serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN] = 0;
nn::cfg::CTR::system::Finalize();
nn::cfg::CTR::init::Finalize();
return result.IsSuccess();
}
//#define setColor(r,g,b,a) s_RenderSystem.SetColor(r,g,b,a)
void setColor(f32 r,f32 g,f32 b,f32 a){ shf_SetColor(r,g,b,a);}
//#define setText(x,y,s) s_RenderSystem.DrawText(x,y,s)
void drawText(u16 x,u16 y,char *s){ shf_DrawText_0( x,y,s);}
//上はASCIIのみ対応したTextWriterへのラッパ
//日本語表示の場合、WideTextWriterを使う(要sft_側の関数追加)
nn::hid::PadReader *hpr;
//---------------------------------------------------------------- 入力待ち
nn::hid::PadStatus padStatus;
u32 WaitKey(u32 mask)
{
while(1){
hpr->ReadLatest(&padStatus);
if(padStatus.trigger & mask)return padStatus.trigger;
CheckSysBreak();
}
}
void endfunc()
{
nn::hid::Finalize();
SharedFontFinalize();
nngxWaitVSync(NN_GX_DISPLAY_BOTH);//SDK2.0以降では不要かも?
s_RenderSystem.Finalize();
}
//署名検証
bool VeriRsa(u8* src,size_t sz,u8* sig)
{
nn::crypto::RsaKey key;
//nn::crypto::Initialize();
nn::ps::CTR::Initialize();
nn::Result res = key.InitializePublicKey(PUBLIC_KEY_BEGIN,KEY_LENGTH);
NN_LOG("inipubkey desc= %d\n",res.GetDescription());
if (res.IsSuccess())
{
res = nn::ps::CTR::VerifyRsaSha256(src,sz,sig,key);
NN_LOG("verisig desc= %d\n",res.GetDescription());
}
//nn::crypto::Finalize();
nn::ps::CTR::Finalize();
return res.IsSuccess();
}
void ErrorStop(char *s)
{
shf_SetScale(0.7,0.7);
setColor(1.0, 0.0, 0.0,1.0);
drawText(10,100,s);
drawText(10,140,"Push Power Button & Power Off");
s_RenderSystem.SwapBuffers();
WaitKey(0);
}
nn::fs::FileInputStream fi;
//ファイルリード
s32 FileRead(char* fname)
{
s32 size;
nn::Result result = fi.TryInitialize(fname);
if (result.IsFailure()){//open error
//NN_LOG("desc= %d\n",result.GetDescription());
return 0;
}
result = fi.TryRead(&size,readBuf,sizeof(readBuf));
fi.Finalize();
if (result.IsFailure()){
//NN_LOG("desc= %d\n",result.GetDescription());
return 0;
}
return size;
}
char ver[16];
char seri[32];
void nnMain( void )
{
nn::Result result;
bool flg_applove=false;
bool flg_test=false;
nn::os::Initialize();
nn::fs::Initialize();
//DEA-SUPにて推奨のフリーズ暫定対策無線デーモンを停止 (2011.3.1 現在)
//ただし、スリープ時の"いつのまに通信"は止まらない
//無線は使わないので本体横スイッチ切っとくのが確実
nn::ndm::SuspendScheduler();
//中断処理の準備
InitSysBreak((uptr)endfunc);
// グラフィックスライブラリの初期化は、以降で行わなければならない
// 他、アプリケーションの初期化処理
nn::hid::Initialize();
nn::hid::PadReader padReader;
hpr = &padReader;
//result = nn::ns::CTR::InitializeForShell();
//if (result.IsSuccess())
result = nn::am::InitializeForLocalImporter();
nn::applet::DisableSleep();//スリープ非対応
const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
static char buffer[ROMFS_BUFFER_SIZE];
// ヒープの確保
appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR);
const u32 s_GxHeapSize = 0x800000;
// RenderSystem の準備
heapForGx = reinterpret_cast<uptr>(appHeap.Allocate(s_GxHeapSize));
s_RenderSystem.Initialize(heapForGx, s_GxHeapSize);
SharedFontInit();
// 共有フォントの種類を取得
//nn::pl::SharedFontType sftype = nn::pl::GetSharedFontType();
// スリープ要求に対する返答を有効にする
// また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する
// nn::applet::EnableSleep(true);
s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
s_RenderSystem.Clear();
// s_RenderSystem.SetFontSize(12);
shf_SetScale(0.8,0.6);
setColor(1.0,1.0,1.0,1.0);
drawText(20,20,"CTR Card Savedata Mover Setup");
s_RenderSystem.SwapBuffers();
shf_SetScale(0.5,0.5);
sprintf(ver,"version %.2f",VERSION);
drawText(250,40,ver);
shf_SetScale(0.7,0.7);
if (result.IsFailure())ErrorStop("Initialize Error");//am 初期化に失敗
//ファイルバッファ
const size_t READ_BUFFER_SIZE = 64*1024;
if (READ_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory allocate fail");
readBuf = reinterpret_cast<u8*>(appHeap.Allocate(READ_BUFFER_SIZE,32));
//シリアルチェック
if( GetSerial() )
{//シリアル取得成功
result = nn::fs::MountSdmc();
if (result.IsSuccess())
{
int i,j,n;
s32 fsize = FileRead(INF_FILE);//設定ファイルがあるか
if((fsize < 1024) && (fsize > 0))//サイズチェック
{
n = 0;
while(n < fsize)
{
if (readBuf[n] == '-'){
if (n == fsize-1)break;//終端
n++;
switch (readBuf[n]){
case 'p':// -p .. 本体シリアル表示
strcpy(seri,"s/n: ");
strcat(seri,(char *)serialNo);
shf_SetScale(0.5,0.5);
drawText(10,40,(char*)seri);
shf_SetScale(0.7,0.7);
break;
case 't':// -t .. テストメニュー有効
flg_test = true;
break;
}
}
n++;
}
}
fsize = FileRead(SIGN_FILE);//署名リード
if(fsize == 256)//サイズチェック
{
memcpy(sign,readBuf,256);//readBuf -> sign
{
fsize = FileRead(LIST_FILE);//リストリード
if((fsize < LIST_MAX * (nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1)) && (fsize > 0))//サイズチェック
{
if (VeriRsa(readBuf,fsize,sign))
{//署名検証OK
int list_ct = 0;
n=0;
u8 d;
while(n < fsize)//リスト作成
{
if ((fsize-n) > nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN)j = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN;
else j = fsize-n;
for (i=0;i<j;i++)
{
d = readBuf[n];
n++;
if ((d==0x0d)||(d==0x0a)) //改行コード
{
if (readBuf[n]==0x0a)n++;//CR+LF,LF+LF
else ErrorStop("list broken");//CRのみは異常、署名時にファイル壊れてた
break;
}
s_list[list_ct][i] = d;
}
if (i>0){
s_list[list_ct][i] = 0;//終端
list_ct++;
if (list_ct>=LIST_MAX)
{//上限オーバー: おそらくリスト作成ミス
ErrorStop("List too Long");
}
}
}
//本体シリアルがリストにあるかチェック
n =0;
int len = strlen((char*)serialNo);
if (len > nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN)len = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN;
while(n<list_ct){
for(i=0;i<len;i++)
{
if (serialNo[i] != s_list[n][i])break;
}
if (i == len)
{
flg_applove = true;
break;
}
}
}//Verify
}//LIST_FILE
}//PUBK_FILE
}//SIGN_FILE
nn::fs::Unmount("sdmc:");
}//MountSdmc
}//GetSerial
NN_LOG("result = %d\n",result.GetDescription());
u32 mask = 0;
if (flg_applove)//インポート許可本体
{
drawText(80,100,"Push X : Import");
drawText(80,140,"Push Y : Delete");
mask |= nn::hid::BUTTON_X | nn::hid::BUTTON_Y;
}
if (flg_test)//テストメニュー
{
drawText(80,160,"Push R : Test Data");
mask |= nn::hid::BUTTON_R;
}
s_RenderSystem.SwapBuffers();
if (mask == 0)ErrorStop("Serial number Check Failed");
u32 trg = WaitKey(mask);
if (trg & nn::hid::BUTTON_R){
shf_SetScale(0.6,0.6);
TestMain();//テストデータへ
}
nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE);
shf_SetScale(0.8,0.8);
// CIA のプログラム ID を取得する。
nn::am::ProgramInfo programInfo;
if (nn::am::GetProgramInfoFromCia(&programInfo, ROMFS_IMPORTEE_PATH).IsFailure())
{
s_RenderSystem.Clear();
setColor(1.0, 0.0, 0.0,1.0);
drawText(10,50,"cia infomation Error");
} else
{
s_RenderSystem.Clear();
if(trg & nn::hid::BUTTON_X) drawText(10,120,"Importing");
else drawText(10,120,"Delete");
s_RenderSystem.SwapBuffers();
// 既に存在するものをインポートするとエラーが返ってくるので、あらかじめ消しておく。
nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, programInfo.id);
// タイトル鍵が違うケースに対応するために、チケットも消しておく。
nn::am::DeleteTicket(programInfo.id);
if(trg & nn::hid::BUTTON_X)
{
// CIA をインポート
if (ImportFile(nn::fs::MEDIA_TYPE_NAND, ROMFS_IMPORTEE_PATH)==false)
{
s_RenderSystem.Clear();
setColor(1.0, 0.0, 0.0,1.0);
drawText(10,50,"Impoprt fail");
s_RenderSystem.SwapBuffers();
}
}
s_RenderSystem.Clear();
drawText(10,50,"Complate");
}
drawText(10,120,"Push Power Button & Power Off");
s_RenderSystem.SwapBuffers();
WaitKey(0);
}