diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.bsf b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.bsf differ diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.rsf b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.rsf new file mode 100644 index 0000000..014621e --- /dev/null +++ b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/FatDataEncrypter.rsf @@ -0,0 +1,44 @@ +BasicInfo: + Title : FatDataEncrypter + ProductCode: FatDataEncrypter + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8021 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - codec + - hid + - gsp + - nwm + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + +CardInfo: + CardDevice: None + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/OMakefile b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/OMakefile new file mode 100644 index 0000000..ada531f --- /dev/null +++ b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/OMakefile @@ -0,0 +1,64 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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$ +#---------------------------------------------------------------------------- +SUPPORTED_TARGETS = CTR-T*.Process.MPCore.* +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = FatDataEncrypter + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../../common + +SOURCES[] = + main.cpp + ../../common/Util.cpp + ../../common/FileTransfer.cpp + ../../common/FileChecker.cpp + ../../common/SdReaderWriter.cpp + ../../common/HeapManager.cpp + ../../common/SdLogger.cpp + ../../common/wave.cpp + ../../common/SimplePlayer.cpp + ../../common/LogConsole.cpp + ../../common/CommonLogger.cpp + ../../common/SdMountManager.cpp + ../../common/configLoader.cpp + ../../common/VersionDetect.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../../common/romfiles + +LIBS += libnn_cfg \ + libnn_crypto \ + libnn_mcu \ + libnn_ps \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + libnn_ns \ + libnn_am \ + libnn_nim \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/model.cbmd b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/model.cbmd differ diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/sound.cbsd b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/sound.cbsd differ diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown24x24.ctpk b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown48x48.ctpk b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/main.cpp b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/main.cpp new file mode 100644 index 0000000..b3e83c9 --- /dev/null +++ b/trunk/ConsoleDataMigration/sources/tools/FatDataEncrypter/main.cpp @@ -0,0 +1,429 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileTransfer.cpp + + Copyright 2009 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Aes_define.h" +#include "FileTransfer.h" +#include "CommonLogger.h" + +#include "demo.h" + +#include +#include + +#include "DrawSystemState.h" +#include "FileName.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "common_Types.h" +#include "VersionDetect.h" +#include "Util.h" +#include "CommonLogger.h" + +namespace +{ + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +const size_t VERIFY_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_EncryptThread; +nn::os::StackBuffer s_EncryptThreadStack; + +u32 s_EncryptSuccess = 0; +u32 s_EncryptFail = 0; + +} + +void GenerateNandPath(wchar_t* toPath, const wchar_t* fromPath) +{ + // 切り詰める + std::string tmp(common::GetCharStr(fromPath)); + std::string twlRoot(common::GetCharStr(common::SD_SAVEDATA_TWL_ROOT_NAME)); + std::string twlPhotoRoot(common::GetCharStr(common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME)); + std::string twlSoundRoot(common::GetCharStr(common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME)); + std::string ctrRoot(common::GetCharStr(common::SD_SAVEDATA_ROOT_NAME)); + + std::string output; + + std::string::size_type size; + size = tmp.find(twlPhotoRoot.c_str()); + if(size == std::string::npos) + { + size = tmp.find(twlSoundRoot.c_str()); + if(size == std::string::npos) + { + size = tmp.find(ctrRoot.c_str()); + if(size == std::string::npos) + { + size = tmp.find(twlRoot.c_str()); + if(size == std::string::npos) + { + // 想定外のパスへの出力のためreturn + return; + } + else + { + output += std::string("twln:/title/"); + output += tmp.substr(size + twlRoot.size()); + } + } + else + { + output += std::string("nand:/data/"); + output += tmp.substr(size + ctrRoot.size()); + } + } + else + { + output += std::string("twls:/"); + output += tmp.substr(size + twlSoundRoot.size()); + } + } + else + { + output += std::string("twlp:/"); + output += tmp.substr(size + twlPhotoRoot.size()); + } + + s32 length = std::mbstowcs(toPath, output.c_str(), nn::fs::MAX_FILE_PATH_LENGTH); + if(length == -1) + { + NN_PANIC("failed mbstowcs"); + } +} + +// ディレクトリ間のコピー +// アーカイブ越しのコピーが可能 +// アーカイブにマウントした状態で呼び出す必要あり +// 書き込み先のディレクトリはあらかじめ消去しておくこと。 +// 引数はスラッシュ付き +// TODO:分割して短くする +bool EncryptDirectory(const wchar_t * from_path, void* buf, + const size_t bufSize) +{ + using namespace common; + + nn::fs::Directory from_dir; + nn::fs::DirectoryEntry entry; + s32 numread = 0; + std::wostringstream target_from; + bool ret_value = true; + + nn::Result result = from_dir.TryInitialize(from_path); + + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return false; + } + + while (1) + { + result = from_dir.TryRead(&numread, &entry, 1); + if (result.IsFailure() || numread != 1) + { + break; + } + + if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) + { + continue; + } + + target_from.str(L""); + target_from.clear(std::stringstream::goodbit); + target_from << from_path << entry.entryName; + + // ディレクトリの場合 + if (entry.attributes.isDirectory) + { + { + target_from << L"/"; + + + // 再帰処理 + if (!EncryptDirectory(target_from.str().c_str(), buf, bufSize)) + { + ret_value = false; + } + } + } + // ファイルの場合 + // SDカード上のファイルを暗号化してCMACを出力する + else + { + nn::fs::FileInputStream sdFile; + s64 filesize; + s32 readsize; + + // 読み込み対象ファイル開く + result = sdFile.TryInitialize(target_from.str().c_str()); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 読み込み対象ファイルのサイズ取得 + result = sdFile.TryGetSize(&filesize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + size_t totalReadSize = 0; + nn::crypto::Sha256Context context; + context.Initialize(); + + // ファイルサイズをヘッダに書いておく + { + wchar_t nandPath[nn::fs::MAX_FILE_PATH_LENGTH]; + // sdパスからnandパスを生成する + GenerateNandPath(nandPath, target_from.str().c_str()); + + // NAND上のフルパスをハッシュに含めている + context.Update(nandPath, std::wcslen(nandPath) * sizeof(wchar_t)); + + BackupDataHeader header; + BackupDataHeader enc; + std::memset(&header, 0, sizeof(header)); + std::memset(&enc, 0, sizeof(enc)); + header.size = filesize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(&enc, sizeof(enc)); + } + + while (1) + { + // バッファの後半半分を暗号・復号用に使う + result = sdFile.TryRead(&readsize, buf, bufSize / 2); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + totalReadSize += readsize; + + if (readsize == 0) + { + { + NN_LOG("Add CMAC %ls\n", target_from.str().c_str()); + // SHA256を計算してCMACを付加する + bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE]; + context.GetHash(sha256Hash); + + bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; + result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, nn::crypto::Sha256Context::HASH_SIZE, + common::cmacKey); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + NN_LOG("cmac:\n"); + for(u32 i = 0; i < sizeof(cmac); i++) + { + NN_LOG("%02X ", cmac[i]); + } + NN_LOG("\n"); + } + + break; + } + else + { + { + NN_LOG("EncryptSize = %d\n", readsize); + + u8 paddingSize = 0; + common::AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readsize); + + // 暗号化後SHA256を計算しつつ書き込み + result = swAesCtrContext.Encrypt(reinterpret_cast(buf) + bufSize / 2, buf, readsize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(reinterpret_cast(buf) + bufSize / 2, readsize); + + // 事前計算したファイルサイズに一致させるためパディング分減算 + readsize -= paddingSize; + } + + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + } + } + sdFile.Finalize(); + } + } + from_dir.Finalize(); + return ret_value; +} + + +void EncryptThreadFunc() +{ + nn::Result result; + + COMMON_LOGGER("EncryptThreadFunc Start\n"); + s_EncryptFail = 0; + s_EncryptSuccess = 0; + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + + common::HeapManager heap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + + EncryptDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME)).c_str(), + buf, bufSize); + + EncryptDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + ::std::wstring(common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME)).c_str(), buf, bufSize); + + EncryptDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + ::std::wstring(common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME)).c_str(), buf, bufSize); + + EncryptDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + buf, bufSize); + } + + common::SdMountManager::Unmount(); + + COMMON_LOGGER("Encrypt Thread Finalize\n"); + + COMMON_LOGGER("\n\n"); + COMMON_LOGGER("Encrypt Finished, success = %d, fail = %d\n", s_EncryptSuccess, s_EncryptFail); +} + +extern "C" void nninitSetupDaemons(void) +{ +} + + +extern "C" void nnMain(void) +{ + nn::Result result; + + // os の初期化 + nn::os::Initialize(); + + // fs の初期化 + nn::fs::Initialize(); + + // appletの初期化 + nn::applet::Enable( false ); + + // hid の初期化 + result = nn::hid::Initialize(); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // ヒープの確保 + common::InitializeHeap(); + + // RenderSystem の準備 + common::HeapManager gxHeap(s_GxHeapSize); + uptr heapForGx = reinterpret_cast(gxHeap.GetAddr()); + demo::RenderSystemDrawing s_RenderSystem; + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + + COMMON_LOGGER("Encrypt Start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + for(;;) + { + s_PadReader.ReadLatest(&padStatus); + + if(padStatus.trigger & nn::hid::BUTTON_A) + { + // SDにコピーするためのスレッドの作成 + if(s_EncryptThread.IsValid() && !s_EncryptThread.IsAlive()) + { + s_EncryptThread.Join(); + s_EncryptThread.Finalize(); + } + s_EncryptThread.Start(EncryptThreadFunc, s_EncryptThreadStack); + } + + // コンソールスクロール + if(padStatus.hold & nn::hid::BUTTON_UP) + { + common::Logger::GetLoggerInstance()->ScrollUp(); + } + + // コンソールスクロール + if(padStatus.hold & nn::hid::BUTTON_DOWN) + { + common::Logger::GetLoggerInstance()->ScrollDown(); + } + + if(padStatus.hold & nn::hid::BUTTON_LEFT) + { + common::Logger::GetLoggerInstance()->ScrollToBegin(); + } + + if(padStatus.hold & nn::hid::BUTTON_RIGHT) + { + common::Logger::GetLoggerInstance()->ScrollToEnd(); + } + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.Clear(); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + + common::Logger::GetLoggerInstance()->DrawConsole(); + s_RenderSystem.SwapBuffers(); + + s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); + } +}