diff --git a/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp index ab63490..766650e 100644 --- a/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp +++ b/trunk/ConsoleDataMigration/ConsoleBackup/Exporter.cpp @@ -326,7 +326,7 @@ void WriteTwlData(enum common::TWL_PATH_INDEX path) // 進捗表示用 common::InitializeTransferProgress(fileSize); - void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); if (buf != NULL) { wchar_t archiveName[256]; @@ -408,7 +408,7 @@ void ExportThreadFunc() size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); NN_LOG("AllocatableSize = %d\n", bufSize); - void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); if (buf != NULL) { diff --git a/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp index fb0df47..10c5e58 100644 --- a/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp +++ b/trunk/ConsoleDataMigration/ConsoleRestore/Importer.cpp @@ -664,7 +664,7 @@ void ImportThreadFunc() size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); NN_LOG("AllocatableSize = %d\n", bufSize); - void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); if (buf != NULL) { @@ -1316,7 +1316,7 @@ void ImportTwlData(enum common::TWL_PATH_INDEX path) NN_LOG("File Size = %d\n", fileSize); - void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); if (buf != NULL) { wchar_t archiveName[256]; diff --git a/trunk/ConsoleDataMigration/common/Aes_define.h b/trunk/ConsoleDataMigration/common/Aes_define.h index a817305..a31eb56 100644 --- a/trunk/ConsoleDataMigration/common/Aes_define.h +++ b/trunk/ConsoleDataMigration/common/Aes_define.h @@ -20,7 +20,7 @@ namespace common { - const bit8 key[AES_KEY_SIZE] = + const bit8 key[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) = { 0x81, 0x35, 0xc6, 0x54, 0x19, 0x1a, 0x47, 0x2a, 0x6b, 0x78, 0xbe, 0x25, 0x90, 0xf6, 0xee, 0x74 @@ -32,13 +32,11 @@ namespace common 0x04, 0x21, 0x9c, 0x5e, 0x33, 0x8c, 0x3d, 0xaa }; - const bit8 iv[AES_BLOCK_SIZE] = + const bit8 iv[AES_BLOCK_SIZE] NN_ATTRIBUTE_ALIGN(4) = { 0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f, 0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9 }; - - } #endif /* AES_DEFINE_H_ */ diff --git a/trunk/ConsoleDataMigration/common/FileTransfer.cpp b/trunk/ConsoleDataMigration/common/FileTransfer.cpp index 091ea9a..7ce23f6 100644 --- a/trunk/ConsoleDataMigration/common/FileTransfer.cpp +++ b/trunk/ConsoleDataMigration/common/FileTransfer.cpp @@ -23,6 +23,7 @@ #include "Aes_define.h" #include "FileTransfer.h" #include "CommonLogger.h" +#include "common_Types.h" namespace common { @@ -173,6 +174,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf nn::fs::FileInputStream from_file; nn::fs::FileOutputStream to_file; s64 filesize; + s64 fileSizeWithoutHeaderAndFooter; s32 readsize; s32 writesize; @@ -209,126 +211,192 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf } } - // 書き込み対象ファイル作成 - result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); - result = to_file.TryInitialize(target_to.str().c_str(), false); - if (result.IsFailure()) + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + size_t totalReadSize = 0; + nn::crypto::Sha256Context context; + context.Initialize(); + + // ファイルサイズをヘッダに書いておく + if (encode) { - nn::dbg::PrintResult(result); - ret_value = false; + // 書き込み対象ファイル作成 + result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); + result = to_file.TryInitialize(target_to.str().c_str(), false); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + + BackupDataHeader header; + BackupDataHeader enc; + header.size = filesize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + context.Update(&enc, sizeof(enc)); + s32 writeSize; + result = to_file.TryWrite(&writeSize, &enc, sizeof(enc), false); + if (result.IsFailure()) + { + ret_value = false; + continue; + } } else { - nn::crypto::SwAesCtrContext swAesCtrContest; - swAesCtrContest.Initialize(iv, common::key, sizeof(key)); - - size_t totalReadSize = 0; - nn::crypto::Sha256Context context; - context.Initialize(); - - while (1) + // ヘッダを読む + // ハッシュの計算は終わっているので復号化のみ + BackupDataHeader header; + BackupDataHeader dec; + s32 readSize; + result = from_file.TryRead(&readSize, &header, sizeof(header)); + if (result.IsFailure()) { - // バッファの後半半分を暗号・復号用に使う - result = from_file.TryRead(&readsize, buf, bufSize / 2); - totalReadSize += readsize; + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + continue; + } + s_FinishedFileSize += sizeof(header); + swAesCtrContext.Decrypt(&dec, &header, sizeof(header)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + fileSizeWithoutHeaderAndFooter = dec.size; - if (result.IsFailure()) + // 書き込み対象ファイル作成 + result = nn::fs::TryCreateFile(target_to.str().c_str(), fileSizeWithoutHeaderAndFooter); + result = to_file.TryInitialize(target_to.str().c_str(), false); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + } + + while (1) + { + // バッファの後半半分を暗号・復号用に使う + result = from_file.TryRead(&readsize, buf, bufSize / 2); + totalReadSize += readsize; + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + break; + } + else + { + if (readsize == 0) { - nn::dbg::PrintResult(result); - ret_value = false; + if (encode) + { + 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_RESULT_IF_FAILED_WITH_LINE(result); + + result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + } + } + + result = to_file.TryFlush(); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } break; } else { - if (readsize == 0) + if (encode) { - if(encode) + NN_LOG("EncryptSize = %d\n", readsize); + + u8 paddingSize = 0; + // 最後の書き込み時にはPKCS5でパディングする + if (readsize < bufSize / 2) { - 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_RESULT_IF_FAILED_WITH_LINE(result); - - result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); - if(result.IsFailure()) + if ((readsize % AES_BLOCK_SIZE) != 0) { - COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); - ret_value = false; + paddingSize = AES_BLOCK_SIZE - readsize % AES_BLOCK_SIZE; + std::memset(reinterpret_cast (buf) + readsize, paddingSize, + paddingSize); + readsize += paddingSize; } } - result = to_file.TryFlush(); - if (result.IsFailure()) - { - nn::dbg::PrintResult(result); - ret_value = false; - } - break; + // 暗号化後SHA256を計算しつつ書き込み + result = swAesCtrContext.Encrypt(reinterpret_cast (buf) + bufSize / 2, buf, + readsize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + context.Update(reinterpret_cast (buf) + bufSize / 2, readsize); + + result = to_file.TryWrite(&writesize, reinterpret_cast (buf) + bufSize / 2, + readsize, false); + + // 事前計算したファイルサイズに一致させるためパディング分減算 + readsize -= paddingSize; + + s_FinishedFileSize += readsize; + s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; + NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); } else { - if (encode) - { - // 暗号化後SHA256を計算しつつ書き込み - result = swAesCtrContest.Encrypt(reinterpret_cast (buf) + bufSize / 2, - buf, readsize); - COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); - context.Update(reinterpret_cast (buf) + bufSize / 2, readsize); + // ハッシュ検証は通っているので復号化しつつ書き込み + // パディング以降は書き込まないよう書き込みサイズを変更する - result = to_file.TryWrite(&writesize, reinterpret_cast(buf) + bufSize / 2 , readsize, false); - s_FinishedFileSize += readsize; - s_Progress = s_FinishedFileSize * 100/ s_TotalFileSize; - NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); + NN_LOG("DecryptSize = %d\n", readsize); + result = swAesCtrContext.Decrypt(reinterpret_cast (buf) + bufSize / 2, buf, + readsize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // パディングまで読んだかどうか + bool readDone = false; + // パディングまで読んでいたら書き込みサイズを減らす + if (fileSizeWithoutHeaderAndFooter < totalReadSize) + { + readsize -= totalReadSize - fileSizeWithoutHeaderAndFooter; + readDone = true; + s_FinishedFileSize += totalReadSize - fileSizeWithoutHeaderAndFooter; } - else - { - // ハッシュ検証は通っているので復号化しつつ書き込み - // ハッシュ部分は書き込まないよう書き込みサイズを取得する - // ハッシュ部分まで読んだかどうか - bool readDone = false; - // ハッシュ部分まで読んでいたら書き込みサイズを減らす - size_t fileSizeWithoutCmac = filesize - nn::crypto::AES_CMAC_MAC_SIZE; - if (fileSizeWithoutCmac < totalReadSize) + result = to_file.TryWrite(&writesize, reinterpret_cast (buf) + bufSize / 2, + readsize, false); + s_FinishedFileSize += readsize; + s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; + NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); + + // 読みきったので次のファイルへ + if (readDone) + { + result = to_file.TryFlush(); + if (result.IsFailure()) { - readsize -= totalReadSize - fileSizeWithoutCmac; - readDone = true; - s_FinishedFileSize += nn::crypto::AES_CMAC_MAC_SIZE; + ret_value = false; } - - result = swAesCtrContest.Decrypt(reinterpret_cast(buf) + bufSize / 2, buf, readsize); COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); - - result = to_file.TryWrite(&writesize, reinterpret_cast(buf) + bufSize / 2 , readsize, false); - s_FinishedFileSize += readsize; - s_Progress = s_FinishedFileSize * 100/ s_TotalFileSize; - NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); - - // 読みきったので次のファイルへ - if (readDone) - { - result = to_file.TryFlush(); - if (result.IsFailure()) - { - ret_value = false; - } - COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); - break; - } + break; } - - - if (result.IsFailure()) - { - nn::dbg::PrintResult(result); - ret_value = false; - } - } + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + } } } diff --git a/trunk/ConsoleDataMigration/common/common_Types.h b/trunk/ConsoleDataMigration/common/common_Types.h index 8424837..2a354a3 100644 --- a/trunk/ConsoleDataMigration/common/common_Types.h +++ b/trunk/ConsoleDataMigration/common/common_Types.h @@ -80,6 +80,13 @@ const nn::ProgramId cNupVerId[] = nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU, }; +struct BackupDataHeader +{ + s64 size; // パディングを含まないファイルサイズ + NN_PADDING4; + NN_PADDING4; +}; + } #endif /* COMMON_TYPES_H_ */