mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-02 13:01:18 +12:00
FST: Refactor IV handling
This commit is contained in:
parent
783d88a892
commit
7168d20cde
3 changed files with 25 additions and 17 deletions
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#define SET_FST_ERROR(__code) if (errorCodeOut) *errorCodeOut = ErrorCode::__code
|
#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
|
class FSTDataSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -868,7 +870,7 @@ static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE);
|
||||||
struct FSTCachedRawBlock
|
struct FSTCachedRawBlock
|
||||||
{
|
{
|
||||||
FSTRawBlock blockData;
|
FSTRawBlock blockData;
|
||||||
uint8 ivForNextBlock[16];
|
NCrypto::AesIv ivForNextBlock;
|
||||||
uint64 lastAccess;
|
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)
|
if(blockIndex == 0)
|
||||||
{
|
{
|
||||||
ivOut[0] = (uint8)(clusterIndex >> 8);
|
ivOut.iv[0] = (uint8)(clusterIndex >> 8);
|
||||||
ivOut[1] = (uint8)(clusterIndex >> 0);
|
ivOut.iv[1] = (uint8)(clusterIndex >> 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -936,20 +938,20 @@ void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex,
|
||||||
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
|
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
|
||||||
if (itr != m_cacheDecryptedRawBlocks.end())
|
if (itr != m_cacheDecryptedRawBlocks.end())
|
||||||
{
|
{
|
||||||
memcpy(ivOut, itr->second->ivForNextBlock, 16);
|
ivOut = itr->second->ivForNextBlock;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cemu_assert(m_sectorSize >= 16);
|
cemu_assert(m_sectorSize >= NCrypto::AesIv::SIZE);
|
||||||
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
|
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
|
||||||
uint8 prevIV[16];
|
NCrypto::AesIv prevIV{};
|
||||||
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - 16, prevIV, 16) != 16)
|
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");
|
cemuLog_log(LogType::Force, "Failed to read IV for raw FST block");
|
||||||
m_detectedCorruption = true;
|
m_detectedCorruption = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(ivOut, prevIV, 16);
|
ivOut = prevIV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,10 +986,10 @@ FSTCachedRawBlock* FSTVolume::GetDecryptedRawBlock(uint32 clusterIndex, uint32 b
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// decrypt hash data
|
// decrypt hash data
|
||||||
uint8 iv[16]{};
|
NCrypto::AesIv iv{};
|
||||||
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
|
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
|
||||||
memcpy(block->ivForNextBlock, block->blockData.rawData.data() + m_sectorSize - 16, 16);
|
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);
|
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 this is the next block, then hash it
|
||||||
if(cluster.hasContentHash)
|
if(cluster.hasContentHash)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,7 +83,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* FST data (in memory) */
|
/* FST data (in memory) */
|
||||||
enum class ClusterHashMode : uint8
|
enum class ClusterHashMode : uint8
|
||||||
{
|
{
|
||||||
|
@ -193,7 +192,7 @@ private:
|
||||||
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
|
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
|
||||||
uint64 m_cacheAccessCounter{};
|
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 FSTCachedRawBlock* GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex);
|
||||||
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);
|
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);
|
||||||
|
|
|
@ -13,10 +13,17 @@ namespace NCrypto
|
||||||
std::string base64Encode(const void* inputMem, size_t inputLen);
|
std::string base64Encode(const void* inputMem, size_t inputLen);
|
||||||
std::vector<uint8> base64Decode(std::string_view inputStr);
|
std::vector<uint8> base64Decode(std::string_view inputStr);
|
||||||
|
|
||||||
/* key helper struct */
|
/* key and iv helper struct */
|
||||||
struct AesKey
|
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 */
|
/* ECC Certificate */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue