mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
nand:/data以下出力時にAES暗号化し、ファイルのSHA256を計算してAES-CMACを付加するように
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@137 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
parent
eff9bf92df
commit
4dc123cbf9
@ -225,12 +225,6 @@ void WriteIvs()
|
||||
{
|
||||
COMMON_LOGGER("Export IVS.\n");
|
||||
|
||||
bit8 iv[AES_BLOCK_SIZE] =
|
||||
{
|
||||
0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f,
|
||||
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
||||
};
|
||||
|
||||
void* ivs;
|
||||
size_t size;
|
||||
GetIvs(&ivs, &size);
|
||||
@ -245,7 +239,7 @@ void WriteIvs()
|
||||
|
||||
nn::crypto::SwAesCtrContext swAesCtrContest;
|
||||
|
||||
swAesCtrContest.Initialize(iv, common::key, sizeof(common::key));
|
||||
swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key));
|
||||
swAesCtrContest.Encrypt(enc, ivs, size);
|
||||
|
||||
s_SdWriter.WriteBufWithCmac(common::IVS_PATHNAME, enc, size);
|
||||
@ -341,7 +335,7 @@ void WriteTwlData(enum common::TWL_PATH_INDEX path)
|
||||
common::CopyDirectory(
|
||||
(archiveString + ::std::wstring(L"/")).c_str(),
|
||||
(common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(),
|
||||
buf, bufSize);
|
||||
buf, bufSize, true);
|
||||
|
||||
common::HeapManager::GetHeap()->Free(buf);
|
||||
}
|
||||
@ -421,7 +415,7 @@ void ExportThreadFunc()
|
||||
common::CopyDirectory(
|
||||
(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(),
|
||||
(common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(),
|
||||
buf, bufSize);
|
||||
buf, bufSize, true);
|
||||
|
||||
common::HeapManager::GetHeap()->Free(buf);
|
||||
}
|
||||
|
||||
@ -81,13 +81,6 @@ void ImportSaveData();
|
||||
// SDからNORにNORデータをコピーする
|
||||
void ImportNorData();
|
||||
|
||||
// IVS復号化用IV
|
||||
bit8 s_IvsDecryptIv[AES_BLOCK_SIZE] =
|
||||
{
|
||||
0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f,
|
||||
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
||||
};
|
||||
|
||||
// SDカードに保存してあるバージョン情報
|
||||
common::VerDef s_SDVersionData;
|
||||
|
||||
@ -591,7 +584,7 @@ void ImportIvs()
|
||||
nn::crypto::Initialize();
|
||||
nn::crypto::SwAesCtrContext swAesCtrContest;
|
||||
|
||||
swAesCtrContest.Initialize(s_IvsDecryptIv, common::key, sizeof(common::key));
|
||||
swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key));
|
||||
swAesCtrContest.Decrypt(dec, enc, readSize);
|
||||
|
||||
// IVS書き込み
|
||||
@ -646,7 +639,7 @@ void ImportThreadFunc()
|
||||
common::CopyDirectory(
|
||||
(::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(),
|
||||
common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH,
|
||||
buf, bufSize);
|
||||
buf, bufSize, false);
|
||||
|
||||
common::HeapManager::GetHeap()->Free(buf);
|
||||
}
|
||||
@ -1291,7 +1284,7 @@ void ImportTwlData(enum common::TWL_PATH_INDEX path)
|
||||
common::CopyDirectory(
|
||||
(::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(),
|
||||
(archiveString + ::std::wstring(L"/")).c_str(),
|
||||
buf, bufSize);
|
||||
buf, bufSize, false);
|
||||
|
||||
common::HeapManager::GetHeap()->Free(buf);
|
||||
}
|
||||
|
||||
@ -31,6 +31,14 @@ namespace common
|
||||
0x87, 0xdd, 0xc6, 0xd6, 0xf2, 0xe0, 0x2c, 0xa6,
|
||||
0x04, 0x21, 0x9c, 0x5e, 0x33, 0x8c, 0x3d, 0xaa
|
||||
};
|
||||
|
||||
const bit8 iv[AES_BLOCK_SIZE] =
|
||||
{
|
||||
0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f,
|
||||
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif /* AES_DEFINE_H_ */
|
||||
|
||||
@ -13,9 +13,17 @@
|
||||
$Rev$
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "FileTransfer.h"
|
||||
#include <vector>
|
||||
|
||||
#include <nn/crypto/crypto_AesCmac.h>
|
||||
#include <nn/crypto/crypto_SwAesCtrContext.h>
|
||||
#include <nn/crypto/crypto_Sha256.h>
|
||||
#include <nn/crypto/crypto_SwAesCmac.h>
|
||||
|
||||
#include "Aes_define.h"
|
||||
#include "FileTransfer.h"
|
||||
#include "CommonLogger.h"
|
||||
|
||||
namespace common
|
||||
{
|
||||
|
||||
@ -28,6 +36,17 @@ u64 s_Progress = 0;
|
||||
|
||||
}
|
||||
|
||||
bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize);
|
||||
|
||||
const char* GetCharStr(const wchar_t* path)
|
||||
{
|
||||
static char filename[256];
|
||||
std::memset(filename, 0, sizeof(filename));
|
||||
std::wcstombs(filename, path, sizeof(filename));
|
||||
filename[sizeof(filename) - 1] = '\0';
|
||||
return filename;
|
||||
}
|
||||
|
||||
nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize)
|
||||
{
|
||||
nn::fs::FileInputStream fis;
|
||||
@ -86,7 +105,8 @@ nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fi
|
||||
// アーカイブにマウントした状態で呼び出す必要あり
|
||||
// 書き込み先のディレクトリはあらかじめ消去しておくこと。
|
||||
// 引数はスラッシュ付き
|
||||
bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize)
|
||||
// TODO:分割して短くする
|
||||
bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize, bool encode)
|
||||
{
|
||||
nn::fs::Directory from_dir;
|
||||
nn::fs::DirectoryEntry entry;
|
||||
@ -140,7 +160,7 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
||||
target_from << L"/";
|
||||
target_to << L"/";
|
||||
// 再帰処理
|
||||
if (!CopyDirectory(target_from.str().c_str(), target_to.str().c_str(), buf, bufSize))
|
||||
if (!CopyDirectory(target_from.str().c_str(), target_to.str().c_str(), buf, bufSize, encode))
|
||||
{
|
||||
ret_value = false;
|
||||
}
|
||||
@ -177,6 +197,18 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 書き込み対象ファイル作成
|
||||
result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize);
|
||||
result = to_file.TryInitialize(target_to.str().c_str(), false);
|
||||
@ -187,9 +219,18 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
||||
}
|
||||
else
|
||||
{
|
||||
nn::crypto::SwAesCtrContext swAesCtrContest;
|
||||
swAesCtrContest.Initialize(iv, common::key, sizeof(key));
|
||||
|
||||
size_t totalReadSize = 0;
|
||||
nn::crypto::Sha256Context context;
|
||||
context.Initialize();
|
||||
|
||||
while (1)
|
||||
{
|
||||
result = from_file.TryRead(&readsize, buf, bufSize);
|
||||
// バッファの後半半分を暗号・復号用に使う
|
||||
result = from_file.TryRead(&readsize, buf, bufSize / 2);
|
||||
totalReadSize += readsize;
|
||||
|
||||
if (result.IsFailure())
|
||||
{
|
||||
@ -201,6 +242,25 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
||||
{
|
||||
if (readsize == 0)
|
||||
{
|
||||
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())
|
||||
{
|
||||
@ -211,15 +271,63 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
||||
}
|
||||
else
|
||||
{
|
||||
result = to_file.TryWrite(&writesize, buf, 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 (encode)
|
||||
{
|
||||
// 暗号化後SHA256を計算しつつ書き込み
|
||||
result = swAesCtrContest.Encrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2,
|
||||
buf, readsize);
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
context.Update(reinterpret_cast<bit8*> (buf) + bufSize / 2, readsize);
|
||||
|
||||
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*>(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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ハッシュ検証は通っているので復号化しつつ書き込み
|
||||
// ハッシュ部分は書き込まないよう書き込みサイズを取得する
|
||||
|
||||
// ハッシュ部分まで読んだかどうか
|
||||
bool readDone = false;
|
||||
// ハッシュ部分まで読んでいたら書き込みサイズを減らす
|
||||
size_t fileSizeWithoutCmac = filesize - nn::crypto::AES_CMAC_MAC_SIZE;
|
||||
if (fileSizeWithoutCmac < totalReadSize)
|
||||
{
|
||||
readsize -= totalReadSize - fileSizeWithoutCmac;
|
||||
readDone = true;
|
||||
s_FinishedFileSize += nn::crypto::AES_CMAC_MAC_SIZE;
|
||||
}
|
||||
|
||||
result = swAesCtrContest.Decrypt(reinterpret_cast<bit8*>(buf) + bufSize / 2, buf, readsize);
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
|
||||
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (result.IsFailure())
|
||||
{
|
||||
nn::dbg::PrintResult(result);
|
||||
ret_value = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,4 +354,113 @@ void InitializeTransferProgress(u64 totalSize)
|
||||
s_FinishedFileSize = 0;
|
||||
}
|
||||
|
||||
bool CalculateAndCompareCmac(nn::crypto::Sha256Context* context, bit8* sdCmac)
|
||||
{
|
||||
nn::Result result;
|
||||
bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE];
|
||||
bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE];
|
||||
|
||||
context->GetHash(sha256Hash);
|
||||
context->Finalize();
|
||||
|
||||
result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, sizeof(sha256Hash), common::cmacKey);
|
||||
if (result.IsFailure())
|
||||
{
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::memcmp(cmac, sdCmac, sizeof(cmac)) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize)
|
||||
{
|
||||
nn::Result result;
|
||||
bit8 sdCmac[nn::crypto::AES_CMAC_MAC_SIZE];
|
||||
|
||||
// ハッシュが付加されていないとエラー
|
||||
if(filesize < nn::crypto::AES_CMAC_MAC_SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 readSize;
|
||||
// ハッシュを取得する
|
||||
nn::crypto::Initialize();
|
||||
result = file->TrySetPosition(filesize - nn::crypto::AES_CMAC_MAC_SIZE);
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
result = file->TryRead(&readSize, sdCmac, sizeof(sdCmac));
|
||||
if(result.IsFailure())
|
||||
{
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
file->SetPosition(0);
|
||||
|
||||
// ハッシュを計算する
|
||||
nn::crypto::Sha256Context context;
|
||||
context.Initialize();
|
||||
bool ret_value = false;
|
||||
|
||||
size_t totalReadSize = 0;
|
||||
while (1)
|
||||
{
|
||||
result = file->TryRead(&readSize, buf, bufSize);
|
||||
totalReadSize += readSize;
|
||||
|
||||
if (result.IsFailure())
|
||||
{
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readSize == 0)
|
||||
{
|
||||
ret_value = CalculateAndCompareCmac(&context, sdCmac);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (result.IsFailure())
|
||||
{
|
||||
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||
ret_value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nn::crypto::Finalize();
|
||||
|
||||
file->SetPosition(0);
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ namespace common
|
||||
{
|
||||
|
||||
nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize);
|
||||
bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize);
|
||||
bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize, bool encode);
|
||||
u32 GetProgress();
|
||||
void InitializeTransferProgress(u64 totalSize);
|
||||
|
||||
|
||||
@ -23,6 +23,8 @@
|
||||
#include <nn/crypto/crypto_Sha256.h>
|
||||
#include <nn/crypto/crypto_SwAesCmac.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace common
|
||||
{
|
||||
|
||||
@ -216,7 +218,10 @@ nn::Result SdReaderWriter::ReadBufWithCmac(const wchar_t* path, void* buf, size_
|
||||
if(std::memcmp(reinterpret_cast<bit8*>(buf) + *totalSize, cmac, sizeof(cmac)) != 0)
|
||||
{
|
||||
// 無効なファイル
|
||||
COMMON_LOGGER("Verification Failed\n");
|
||||
char filename[256];
|
||||
std::wcstombs(filename, path, sizeof(filename));
|
||||
filename[sizeof(filename) - 1] = '\0';
|
||||
COMMON_LOGGER("Verification Failed %s\n", filename);
|
||||
return nn::fs::ResultVerificationFailed();
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user