mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
ソフトAES CTRモードが16バイトブロックモードのみのためPKCS#5でパディングするように
SD出力ファイルの先頭にヘッダをつけてファイルサイズを取得できるように NAND書き込み時のファイルサイズを正しく設定するように CopyDirectoryには16バイトアラインしたバッファを渡すように git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@140 385bec56-5757-e545-9c3a-d8741f4650f1
This commit is contained in:
parent
b7781d4f37
commit
1ade502635
@ -326,7 +326,7 @@ void WriteTwlData(enum common::TWL_PATH_INDEX path)
|
|||||||
// 進捗表示用
|
// 進捗表示用
|
||||||
common::InitializeTransferProgress(fileSize);
|
common::InitializeTransferProgress(fileSize);
|
||||||
|
|
||||||
void* buf = common::HeapManager::GetHeap()->Allocate(bufSize);
|
void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE);
|
||||||
if (buf != NULL)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
wchar_t archiveName[256];
|
wchar_t archiveName[256];
|
||||||
@ -408,7 +408,7 @@ void ExportThreadFunc()
|
|||||||
size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize();
|
size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize();
|
||||||
NN_LOG("AllocatableSize = %d\n", bufSize);
|
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)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@ -664,7 +664,7 @@ void ImportThreadFunc()
|
|||||||
size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize();
|
size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize();
|
||||||
NN_LOG("AllocatableSize = %d\n", bufSize);
|
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)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1316,7 +1316,7 @@ void ImportTwlData(enum common::TWL_PATH_INDEX path)
|
|||||||
NN_LOG("File Size = %d\n", fileSize);
|
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)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
wchar_t archiveName[256];
|
wchar_t archiveName[256];
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
namespace common
|
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,
|
0x81, 0x35, 0xc6, 0x54, 0x19, 0x1a, 0x47, 0x2a,
|
||||||
0x6b, 0x78, 0xbe, 0x25, 0x90, 0xf6, 0xee, 0x74
|
0x6b, 0x78, 0xbe, 0x25, 0x90, 0xf6, 0xee, 0x74
|
||||||
@ -32,13 +32,11 @@ namespace common
|
|||||||
0x04, 0x21, 0x9c, 0x5e, 0x33, 0x8c, 0x3d, 0xaa
|
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,
|
0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f,
|
||||||
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* AES_DEFINE_H_ */
|
#endif /* AES_DEFINE_H_ */
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "Aes_define.h"
|
#include "Aes_define.h"
|
||||||
#include "FileTransfer.h"
|
#include "FileTransfer.h"
|
||||||
#include "CommonLogger.h"
|
#include "CommonLogger.h"
|
||||||
|
#include "common_Types.h"
|
||||||
|
|
||||||
namespace common
|
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::FileInputStream from_file;
|
||||||
nn::fs::FileOutputStream to_file;
|
nn::fs::FileOutputStream to_file;
|
||||||
s64 filesize;
|
s64 filesize;
|
||||||
|
s64 fileSizeWithoutHeaderAndFooter;
|
||||||
s32 readsize;
|
s32 readsize;
|
||||||
s32 writesize;
|
s32 writesize;
|
||||||
|
|
||||||
@ -209,126 +211,192 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 書き込み対象ファイル作成
|
nn::crypto::SwAesCtrContext swAesCtrContext;
|
||||||
result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize);
|
swAesCtrContext.Initialize(iv, common::key, sizeof(key));
|
||||||
result = to_file.TryInitialize(target_to.str().c_str(), false);
|
|
||||||
if (result.IsFailure())
|
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
|
else
|
||||||
{
|
{
|
||||||
nn::crypto::SwAesCtrContext swAesCtrContest;
|
// ヘッダを読む
|
||||||
swAesCtrContest.Initialize(iv, common::key, sizeof(key));
|
// ハッシュの計算は終わっているので復号化のみ
|
||||||
|
BackupDataHeader header;
|
||||||
size_t totalReadSize = 0;
|
BackupDataHeader dec;
|
||||||
nn::crypto::Sha256Context context;
|
s32 readSize;
|
||||||
context.Initialize();
|
result = from_file.TryRead(&readSize, &header, sizeof(header));
|
||||||
|
if (result.IsFailure())
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
// バッファの後半半分を暗号・復号用に使う
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||||
result = from_file.TryRead(&readsize, buf, bufSize / 2);
|
ret_value = false;
|
||||||
totalReadSize += readsize;
|
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);
|
if (encode)
|
||||||
ret_value = false;
|
{
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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());
|
if ((readsize % AES_BLOCK_SIZE) != 0)
|
||||||
// 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);
|
paddingSize = AES_BLOCK_SIZE - readsize % AES_BLOCK_SIZE;
|
||||||
ret_value = false;
|
std::memset(reinterpret_cast<bit8*> (buf) + readsize, paddingSize,
|
||||||
|
paddingSize);
|
||||||
|
readsize += paddingSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = to_file.TryFlush();
|
// 暗号化後SHA256を計算しつつ書き込み
|
||||||
if (result.IsFailure())
|
result = swAesCtrContext.Encrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2, buf,
|
||||||
{
|
readsize);
|
||||||
nn::dbg::PrintResult(result);
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||||
ret_value = false;
|
context.Update(reinterpret_cast<bit8*> (buf) + bufSize / 2, readsize);
|
||||||
}
|
|
||||||
break;
|
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*> (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
|
else
|
||||||
{
|
{
|
||||||
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);
|
NN_LOG("DecryptSize = %d\n", readsize);
|
||||||
s_FinishedFileSize += readsize;
|
result = swAesCtrContext.Decrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2, buf,
|
||||||
s_Progress = s_FinishedFileSize * 100/ s_TotalFileSize;
|
readsize);
|
||||||
NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress);
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||||
|
|
||||||
|
// パディングまで読んだかどうか
|
||||||
|
bool readDone = false;
|
||||||
|
// パディングまで読んでいたら書き込みサイズを減らす
|
||||||
|
if (fileSizeWithoutHeaderAndFooter < totalReadSize)
|
||||||
|
{
|
||||||
|
readsize -= totalReadSize - fileSizeWithoutHeaderAndFooter;
|
||||||
|
readDone = true;
|
||||||
|
s_FinishedFileSize += totalReadSize - fileSizeWithoutHeaderAndFooter;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// ハッシュ検証は通っているので復号化しつつ書き込み
|
|
||||||
// ハッシュ部分は書き込まないよう書き込みサイズを取得する
|
|
||||||
|
|
||||||
// ハッシュ部分まで読んだかどうか
|
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*> (buf) + bufSize / 2,
|
||||||
bool readDone = false;
|
readsize, false);
|
||||||
// ハッシュ部分まで読んでいたら書き込みサイズを減らす
|
s_FinishedFileSize += readsize;
|
||||||
size_t fileSizeWithoutCmac = filesize - nn::crypto::AES_CMAC_MAC_SIZE;
|
s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize;
|
||||||
if (fileSizeWithoutCmac < totalReadSize)
|
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;
|
ret_value = false;
|
||||||
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);
|
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
|
||||||
|
break;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.IsFailure())
|
||||||
|
{
|
||||||
|
nn::dbg::PrintResult(result);
|
||||||
|
ret_value = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,6 +80,13 @@ const nn::ProgramId cNupVerId[] =
|
|||||||
nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU,
|
nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BackupDataHeader
|
||||||
|
{
|
||||||
|
s64 size; // パディングを含まないファイルサイズ
|
||||||
|
NN_PADDING4;
|
||||||
|
NN_PADDING4;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* COMMON_TYPES_H_ */
|
#endif /* COMMON_TYPES_H_ */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user