From 5ea854b6106063a1fb982c911ce877042e7da47a Mon Sep 17 00:00:00 2001 From: N2614 Date: Fri, 18 Mar 2011 02:57:10 +0000 Subject: [PATCH] =?UTF-8?q?NAND=E3=81=AB=E4=B8=80=E6=99=82=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=A8=E3=81=97=E3=81=A6=E4=BD=9C?= =?UTF-8?q?=E6=88=90=E3=81=97CMAC=E6=A4=9C=E8=A8=BC=E3=81=AB=E9=80=9A?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=8B=E3=82=89=E3=83=AA=E3=83=8D=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20CMAC?= =?UTF-8?q?=E6=A4=9C=E8=A8=BC=E3=81=AB=E5=A4=B1=E6=95=97=E3=81=97=E3=81=9F?= =?UTF-8?q?=E3=82=89NAND=E3=81=8B=E3=82=89=E5=89=8A=E9=99=A4=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20BackupDataHeader?= =?UTF-8?q?=E3=82=920=E3=82=AF=E3=83=AA=E3=82=A2=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=81=8B=E3=82=89=E6=9B=B8=E3=81=8D=E8=BE=BC=E3=82=80=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@148 385bec56-5757-e545-9c3a-d8741f4650f1 --- .../common/FileTransfer.cpp | 199 ++++++++++++------ 1 file changed, 138 insertions(+), 61 deletions(-) diff --git a/trunk/ConsoleDataMigration/common/FileTransfer.cpp b/trunk/ConsoleDataMigration/common/FileTransfer.cpp index 7ce23f6..7371393 100644 --- a/trunk/ConsoleDataMigration/common/FileTransfer.cpp +++ b/trunk/ConsoleDataMigration/common/FileTransfer.cpp @@ -37,7 +37,11 @@ u64 s_Progress = 0; } -bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize); +bool VerifyMac(nn::fs::FileInputStream* sdFile, nn::fs::FileStream* nandFile, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize); +bool ConfirmFile(nn::fs::FileInputStream* from_file, nn::fs::FileStream* to_file, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize, const wchar_t* sdPath, const wchar_t* tmpPath, const wchar_t* truePath); +void AddPkcsPadding(u8* paddingSize, void* buf, size_t bufSize, s32* readSize); const char* GetCharStr(const wchar_t* path) { @@ -120,7 +124,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); return false; } @@ -153,7 +157,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf result = nn::fs::TryCreateDirectory(target_to.str().c_str()); if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } else @@ -170,9 +174,22 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf // ファイルの場合 else { + std::wostringstream target_tmp; + target_tmp.str(L""); + target_tmp.clear(std::stringstream::goodbit); + + if(!encode) + { + target_tmp << to_path << L"_" << entry.entryName; + } + else + { + target_tmp << target_to.str(); + } + // ファイル作成 nn::fs::FileInputStream from_file; - nn::fs::FileOutputStream to_file; + nn::fs::FileStream to_file; s64 filesize; s64 fileSizeWithoutHeaderAndFooter; s32 readsize; @@ -185,7 +202,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } else @@ -194,23 +211,11 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf result = from_file.TryGetSize(&filesize); if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } else { - // 復号するならまず検証する - if(!encode) - { - NN_LOG("Verify CMAC %ls\n", target_from.str().c_str()); - if(!VerifyMac(&from_file, filesize, buf, bufSize)) - { - COMMON_LOGGER("Verification Failed %s\n", GetCharStr(target_from.str().c_str())); - ret_value = false; - break; - } - } - nn::crypto::SwAesCtrContext swAesCtrContext; swAesCtrContext.Initialize(iv, common::key, sizeof(key)); @@ -222,16 +227,20 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf if (encode) { // 書き込み対象ファイル作成 - result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); - result = to_file.TryInitialize(target_to.str().c_str(), false); + result = nn::fs::TryCreateFile(target_tmp.str().c_str(), filesize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = to_file.TryInitialize(target_tmp.str().c_str(), + nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } 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_RESULT_IF_FAILED_WITH_LINE(result); @@ -250,6 +259,8 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf // ハッシュの計算は終わっているので復号化のみ BackupDataHeader header; BackupDataHeader dec; + std::memset(&header, 0, sizeof(header)); + std::memset(&dec, 0, sizeof(dec)); s32 readSize; result = from_file.TryRead(&readSize, &header, sizeof(header)); if (result.IsFailure()) @@ -264,11 +275,13 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf fileSizeWithoutHeaderAndFooter = dec.size; // 書き込み対象ファイル作成 - result = nn::fs::TryCreateFile(target_to.str().c_str(), fileSizeWithoutHeaderAndFooter); - result = to_file.TryInitialize(target_to.str().c_str(), false); + result = nn::fs::TryCreateFile(target_tmp.str().c_str(), fileSizeWithoutHeaderAndFooter); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = to_file.TryInitialize(target_tmp.str().c_str(), + nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } } @@ -281,7 +294,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; break; } @@ -310,11 +323,24 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf } result = to_file.TryFlush(); + if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } + + // 復号済みなら検証する + if (!encode) + { + if (!ConfirmFile(&from_file, &to_file, filesize, fileSizeWithoutHeaderAndFooter, + buf, bufSize, target_from.str().c_str(), target_tmp.str().c_str(), + target_to.str().c_str())) + { + ret_value = false; + } + } + break; } else @@ -324,17 +350,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf NN_LOG("EncryptSize = %d\n", readsize); u8 paddingSize = 0; - // 最後の書き込み時にはPKCS5でパディングする - if (readsize < bufSize / 2) - { - if ((readsize % AES_BLOCK_SIZE) != 0) - { - paddingSize = AES_BLOCK_SIZE - readsize % AES_BLOCK_SIZE; - std::memset(reinterpret_cast (buf) + readsize, paddingSize, - paddingSize); - readsize += paddingSize; - } - } + AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readsize); // 暗号化後SHA256を計算しつつ書き込み result = swAesCtrContext.Encrypt(reinterpret_cast (buf) + bufSize / 2, buf, @@ -387,13 +403,21 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf ret_value = false; } COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + if (!ConfirmFile(&from_file, &to_file, filesize, + fileSizeWithoutHeaderAndFooter, buf, bufSize, + target_from.str().c_str(), target_tmp.str().c_str(), + target_to.str().c_str())) + { + ret_value = false; + } break; } } if (result.IsFailure()) { - nn::dbg::PrintResult(result); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); ret_value = false; } @@ -442,13 +466,14 @@ bool CalculateAndCompareCmac(nn::crypto::Sha256Context* context, bit8* sdCmac) } -bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize) +bool VerifyMac(nn::fs::FileInputStream* sdFile, nn::fs::FileStream* nandFile, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize) { nn::Result result; bit8 sdCmac[nn::crypto::AES_CMAC_MAC_SIZE]; // ハッシュが付加されていないとエラー - if(filesize < nn::crypto::AES_CMAC_MAC_SIZE) + if(sdFileSize < nn::crypto::AES_CMAC_MAC_SIZE) { return false; } @@ -456,10 +481,10 @@ bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bu s32 readSize; // ハッシュを取得する nn::crypto::Initialize(); - result = file->TrySetPosition(filesize - nn::crypto::AES_CMAC_MAC_SIZE); + result = sdFile->TrySetPosition(sdFileSize - nn::crypto::AES_CMAC_MAC_SIZE); if (result.IsSuccess()) { - result = file->TryRead(&readSize, sdCmac, sizeof(sdCmac)); + result = sdFile->TryRead(&readSize, sdCmac, sizeof(sdCmac)); if(result.IsFailure()) { COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); @@ -472,17 +497,32 @@ bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bu return false; } - file->SetPosition(0); + sdFile->Finalize(); + + nandFile->SetPosition(0); // ハッシュを計算する + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + nn::crypto::Sha256Context context; context.Initialize(); + + BackupDataHeader header; + BackupDataHeader enc; + std::memset(&header, 0, sizeof(header)); + std::memset(&enc, 0, sizeof(enc)); + header.size = nandFileSize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + context.Update(&enc, sizeof(enc)); + bool ret_value = false; size_t totalReadSize = 0; while (1) { - result = file->TryRead(&readSize, buf, bufSize); + result = nandFile->TryRead(&readSize, buf, bufSize / 2); totalReadSize += readSize; if (result.IsFailure()) @@ -500,21 +540,11 @@ bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bu } else { - bool readDone = false; - // ハッシュ部分まで読んでいたらハッシュ検証サイズを減らす - size_t fileSizeWithoutCmac = filesize - nn::crypto::AES_CMAC_MAC_SIZE; - if (fileSizeWithoutCmac < totalReadSize) - { - readSize -= totalReadSize - fileSizeWithoutCmac; - readDone = true; - } - - context.Update(buf, readSize); - if(readDone) - { - ret_value = CalculateAndCompareCmac(&context, sdCmac); - break; - } + u8 paddingSize = 0; + AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readSize); + 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); if (result.IsFailure()) { @@ -525,10 +555,57 @@ bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bu } } nn::crypto::Finalize(); - - file->SetPosition(0); + nandFile->Finalize(); return ret_value; } +bool ConfirmFile(nn::fs::FileInputStream* from_file, nn::fs::FileStream* to_file, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize, const wchar_t* sdPath, const wchar_t* tmpPath, const wchar_t* truePath) +{ + nn::Result result; + + bool ret_value = true; + NN_LOG("Verify CMAC %ls\n", sdPath); + if (!VerifyMac(from_file, to_file, sdFileSize, nandFileSize, buf, bufSize)) + { + // 検証に失敗したので削除する + COMMON_LOGGER("Verification Failed %s, Delete\n", GetCharStr(sdPath)); + result = nn::fs::TryDeleteFile(tmpPath); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + } + else + { + NN_LOG("Verification Success %s, Rename\n", GetCharStr(sdPath)); + // リネームする + result = nn::fs::TryRenameFile(tmpPath, truePath); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsFailure()) + { + ret_value = false; + } + } + + return ret_value; +} + +//! @brief 入力データの末尾16バイトをPKCS5で必要バイト数パディングする +//! @param[out] paddingSize パディングしたバイト数 +//! @param[in] buf 入力データの入ったバッファ +//! @param[in] bufSize バッファサイズ +//! @param[inout] readSize バッファに読み込んだバイト数。書き込み時に参照するためパディングしたら増加させる +void AddPkcsPadding(u8* paddingSize, void* buf, size_t bufSize, s32* readSize) +{ + if (*readSize < bufSize) + { + if ((*readSize % AES_BLOCK_SIZE) != 0) + { + *paddingSize = AES_BLOCK_SIZE - *readSize % AES_BLOCK_SIZE; + std::memset(reinterpret_cast(buf) + *readSize, *paddingSize, *paddingSize); + *readSize += *paddingSize; + } + } +} + }