Skip to content

Commit 7168d20

Browse files
committed
FST: Refactor IV handling
1 parent 783d88a commit 7168d20

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

src/Cafe/Filesystem/FST/FST.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#define SET_FST_ERROR(__code) if (errorCodeOut) *errorCodeOut = ErrorCode::__code
1515

16+
static_assert(sizeof(NCrypto::AesIv) == 16); // make sure IV is actually 16 bytes
17+
1618
class FSTDataSource
1719
{
1820
public:
@@ -868,7 +870,7 @@ static_assert(sizeof(FSTHashedBlock) == BLOCK_SIZE);
868870
struct FSTCachedRawBlock
869871
{
870872
FSTRawBlock blockData;
871-
uint8 ivForNextBlock[16];
873+
NCrypto::AesIv ivForNextBlock;
872874
uint64 lastAccess;
873875
};
874876

@@ -919,13 +921,13 @@ void FSTVolume::TrimCacheIfRequired(FSTCachedRawBlock** droppedRawBlock, FSTCach
919921
}
920922
}
921923

922-
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16])
924+
void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut)
923925
{
924-
memset(ivOut, 0, sizeof(ivOut));
926+
ivOut = {};
925927
if(blockIndex == 0)
926928
{
927-
ivOut[0] = (uint8)(clusterIndex >> 8);
928-
ivOut[1] = (uint8)(clusterIndex >> 0);
929+
ivOut.iv[0] = (uint8)(clusterIndex >> 8);
930+
ivOut.iv[1] = (uint8)(clusterIndex >> 0);
929931
}
930932
else
931933
{
@@ -936,20 +938,20 @@ void FSTVolume::DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex,
936938
auto itr = m_cacheDecryptedRawBlocks.find(cacheBlockId);
937939
if (itr != m_cacheDecryptedRawBlocks.end())
938940
{
939-
memcpy(ivOut, itr->second->ivForNextBlock, 16);
941+
ivOut = itr->second->ivForNextBlock;
940942
}
941943
else
942944
{
943-
cemu_assert(m_sectorSize >= 16);
945+
cemu_assert(m_sectorSize >= NCrypto::AesIv::SIZE);
944946
uint64 clusterOffset = (uint64)m_cluster[clusterIndex].offset * m_sectorSize;
945-
uint8 prevIV[16];
946-
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - 16, prevIV, 16) != 16)
947+
NCrypto::AesIv prevIV{};
948+
if (m_dataSource->readData(clusterIndex, clusterOffset, blockIndex * m_sectorSize - NCrypto::AesIv::SIZE, prevIV.iv, NCrypto::AesIv::SIZE) != NCrypto::AesIv::SIZE)
947949
{
948950
cemuLog_log(LogType::Force, "Failed to read IV for raw FST block");
949951
m_detectedCorruption = true;
950952
return;
951953
}
952-
memcpy(ivOut, prevIV, 16);
954+
ivOut = prevIV;
953955
}
954956
}
955957
}
@@ -984,10 +986,10 @@ FSTCachedRawBlock* FSTVolume::GetDecryptedRawBlock(uint32 clusterIndex, uint32 b
984986
return nullptr;
985987
}
986988
// decrypt hash data
987-
uint8 iv[16]{};
989+
NCrypto::AesIv iv{};
988990
DetermineUnhashedBlockIV(clusterIndex, blockIndex, iv);
989-
memcpy(block->ivForNextBlock, block->blockData.rawData.data() + m_sectorSize - 16, 16);
990-
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv);
991+
std::copy(block->blockData.rawData.data() + m_sectorSize - NCrypto::AesIv::SIZE, block->blockData.rawData.data() + m_sectorSize, block->ivForNextBlock.iv);
992+
AES128_CBC_decrypt(block->blockData.rawData.data(), block->blockData.rawData.data(), m_sectorSize, m_partitionTitlekey.b, iv.iv);
991993
// if this is the next block, then hash it
992994
if(cluster.hasContentHash)
993995
{

src/Cafe/Filesystem/FST/FST.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ class FSTVolume
8383
}
8484

8585
private:
86-
8786
/* FST data (in memory) */
8887
enum class ClusterHashMode : uint8
8988
{
@@ -193,7 +192,7 @@ class FSTVolume
193192
std::unordered_map<uint64, struct FSTCachedHashedBlock*> m_cacheDecryptedHashedBlocks;
194193
uint64 m_cacheAccessCounter{};
195194

196-
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, uint8 ivOut[16]);
195+
void DetermineUnhashedBlockIV(uint32 clusterIndex, uint32 blockIndex, NCrypto::AesIv& ivOut);
197196

198197
struct FSTCachedRawBlock* GetDecryptedRawBlock(uint32 clusterIndex, uint32 blockIndex);
199198
struct FSTCachedHashedBlock* GetDecryptedHashedBlock(uint32 clusterIndex, uint32 blockIndex);

src/Cemu/ncrypto/ncrypto.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,17 @@ namespace NCrypto
1313
std::string base64Encode(const void* inputMem, size_t inputLen);
1414
std::vector<uint8> base64Decode(std::string_view inputStr);
1515

16-
/* key helper struct */
16+
/* key and iv helper struct */
1717
struct AesKey
1818
{
19-
uint8 b[16];
19+
static constexpr size_t SIZE = 16;
20+
uint8 b[SIZE];
21+
};
22+
23+
struct AesIv
24+
{
25+
static constexpr size_t SIZE = 16;
26+
uint8 iv[SIZE];
2027
};
2128

2229
/* ECC Certificate */

0 commit comments

Comments
 (0)