ソフト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:
N2614 2011-03-15 11:07:27 +00:00
parent b7781d4f37
commit 1ade502635
5 changed files with 173 additions and 100 deletions

View File

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

View File

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

View File

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

View File

@ -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,6 +211,16 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
} }
} }
nn::crypto::SwAesCtrContext swAesCtrContext;
swAesCtrContext.Initialize(iv, common::key, sizeof(key));
size_t totalReadSize = 0;
nn::crypto::Sha256Context context;
context.Initialize();
// ファイルサイズをヘッダに書いておく
if (encode)
{
// 書き込み対象ファイル作成 // 書き込み対象ファイル作成
result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize);
result = to_file.TryInitialize(target_to.str().c_str(), false); result = to_file.TryInitialize(target_to.str().c_str(), false);
@ -217,14 +229,49 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
nn::dbg::PrintResult(result); nn::dbg::PrintResult(result);
ret_value = false; 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;
BackupDataHeader dec;
s32 readSize;
result = from_file.TryRead(&readSize, &header, sizeof(header));
if (result.IsFailure())
{
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;
size_t totalReadSize = 0; // 書き込み対象ファイル作成
nn::crypto::Sha256Context context; result = nn::fs::TryCreateFile(target_to.str().c_str(), fileSizeWithoutHeaderAndFooter);
context.Initialize(); result = to_file.TryInitialize(target_to.str().c_str(), false);
if (result.IsFailure())
{
nn::dbg::PrintResult(result);
ret_value = false;
}
}
while (1) while (1)
{ {
@ -250,7 +297,8 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
context.GetHash(sha256Hash); context.GetHash(sha256Hash);
bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE];
result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey); result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash,
nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey);
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); result = to_file.TryWrite(&writesize, cmac, sizeof(cmac));
@ -273,13 +321,33 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
{ {
if (encode) if (encode)
{ {
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<bit8*> (buf) + readsize, paddingSize,
paddingSize);
readsize += paddingSize;
}
}
// 暗号化後SHA256を計算しつつ書き込み // 暗号化後SHA256を計算しつつ書き込み
result = swAesCtrContest.Encrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2, result = swAesCtrContext.Encrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2, buf,
buf, readsize); readsize);
COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
context.Update(reinterpret_cast<bit8*> (buf) + bufSize / 2, readsize); context.Update(reinterpret_cast<bit8*> (buf) + bufSize / 2, readsize);
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*>(buf) + bufSize / 2 , readsize, false); result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*> (buf) + bufSize / 2,
readsize, false);
// 事前計算したファイルサイズに一致させるためパディング分減算
readsize -= paddingSize;
s_FinishedFileSize += readsize; s_FinishedFileSize += readsize;
s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize;
NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress);
@ -287,23 +355,25 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
else else
{ {
// ハッシュ検証は通っているので復号化しつつ書き込み // ハッシュ検証は通っているので復号化しつつ書き込み
// ハッシュ部分は書き込まないよう書き込みサイズを取得する // パディング以降は書き込まないよう書き込みサイズを変更する
// ハッシュ部分まで読んだかどうか NN_LOG("DecryptSize = %d\n", readsize);
bool readDone = false; result = swAesCtrContext.Decrypt(reinterpret_cast<bit8*> (buf) + bufSize / 2, buf,
// ハッシュ部分まで読んでいたら書き込みサイズを減らす readsize);
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); COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result);
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*>(buf) + bufSize / 2 , readsize, false); // パディングまで読んだかどうか
bool readDone = false;
// パディングまで読んでいたら書き込みサイズを減らす
if (fileSizeWithoutHeaderAndFooter < totalReadSize)
{
readsize -= totalReadSize - fileSizeWithoutHeaderAndFooter;
readDone = true;
s_FinishedFileSize += totalReadSize - fileSizeWithoutHeaderAndFooter;
}
result = to_file.TryWrite(&writesize, reinterpret_cast<bit8*> (buf) + bufSize / 2,
readsize, false);
s_FinishedFileSize += readsize; s_FinishedFileSize += readsize;
s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize;
NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress);
@ -321,7 +391,6 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
} }
} }
if (result.IsFailure()) if (result.IsFailure())
{ {
nn::dbg::PrintResult(result); nn::dbg::PrintResult(result);
@ -331,7 +400,6 @@ bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf
} }
} }
} }
}
to_file.Finalize(); to_file.Finalize();
} }
} }

View File

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