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:
N2614 2011-03-14 10:02:24 +00:00
parent eff9bf92df
commit 4dc123cbf9
6 changed files with 246 additions and 29 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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();
}