FST: Refactor IV handling
Some checks failed
Build check / build (push) Waiting to run
Generate translation template / generate-pot (push) Failing after 1s

This commit is contained in:
Exzap 2025-05-27 16:51:46 +02:00
parent 783d88a892
commit 7168d20cde
3 changed files with 25 additions and 17 deletions

View file

@ -13,6 +13,8 @@
#define SET_FST_ERROR(__code) if (errorCodeOut) *errorCodeOut = ErrorCode::__code
static_assert(sizeof(NCrypto::AesIv) == 16); // make sure IV is actually 16 bytes
class FSTDataSource
{
public:
@ -868,7 +870,7 @@ static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE);
struct FSTCachedRawBlock
{
FSTRawBlock blockData;
uint8 ivForNextBlock[16];
NCrypto::AesIv ivForNextBlock;
uint64 lastAccess;
};
@ -919,13 +921,13 @@ void FSTVolume::TrimCacheIfRequired(FSTCachedRawBlock** droppedRawBlock, FSTCach
}
}
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16])
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut)
{
memset(ivOut, 0, sizeof(ivOut));
ivOut = {};
if(blockIndex == 0)
{
ivOut[0] = (uint8)(clusterIndex >> 8);
ivOut[1] = (uint8)(clusterIndex >> 0);
ivOut.iv[0] = (uint8)(clusterIndex >> 8);
ivOut.iv[1] = (uint8)(clusterIndex >> 0);
}
else
{
@ -936,20 +938,20 @@ void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex,
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
if (itr != m_cacheDecryptedRawBlocks.end())
{
memcpy(ivOut, itr->second->ivForNextBlock, 16);
ivOut = itr->second->ivForNextBlock;
}
else
{
cemu_assert(m_sectorSize >= 16);
cemu_assert(m_sectorSize >= NCrypto::AesIv::SIZE);
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
uint8 prevIV[16];
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - 16, prevIV, 16) != 16)
NCrypto::AesIv prevIV{};
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - NCrypto::AesIv::SIZE, prevIV.iv, NCrypto::AesIv::SIZE) != NCrypto::AesIv::SIZE)
{
cemuLog_log(LogType::Force, "Failed to read IV for raw FST block");
m_detectedCorruption = true;
return;
}
memcpy(ivOut, prevIV, 16);
ivOut = prevIV;
}
}
}
@ -984,10 +986,10 @@ FSTCachedRawBlock* FSTVolume::GetDecryptedRawBlock(uint32 clusterIndex, uint32 b
return nullptr;
}
// decrypt hash data
uint8 iv[16]{};
NCrypto::AesIv iv{};
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
memcpy(block->ivForNextBlock, block->blockData.rawData.data() + m_sectorSize - 16, 16);
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv);
std::copy(block->blockData.rawData.data() + m_sectorSize - NCrypto::AesIv::SIZE, block->blockData.rawData.data() + m_sectorSize, block->ivForNextBlock.iv);
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv.iv);
// if this is the next block, then hash it
if(cluster.hasContentHash)
{

View file

@ -83,7 +83,6 @@ public:
}
private:
/* FST data (in memory) */
enum class ClusterHashMode : uint8
{
@ -193,7 +192,7 @@ private:
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
uint64 m_cacheAccessCounter{};
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16]);
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut);
struct FSTCachedRawBlock* GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex);
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);

View file

@ -13,10 +13,17 @@ namespace NCrypto
std::string base64Encode(const void* inputMem, size_t inputLen);
std::vector<uint8> base64Decode(std::string_view inputStr);
/* key helper struct */
/* key and iv helper struct */
struct AesKey
{
uint8 b[16];
static constexpr size_t SIZE = 16;
uint8 b[SIZE];
};
struct AesIv
{
static constexpr size_t SIZE = 16;
uint8 iv[SIZE];
};
/* ECC Certificate */