Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VolumeWiiCrypted: Decryption optimization #1969

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 22 additions & 17 deletions Source/Core/DiscIO/VolumeWiiCrypted.cpp
Expand Up @@ -33,7 +33,7 @@ CVolumeWiiCrypted::CVolumeWiiCrypted(IBlobReader* _pReader, u64 _VolumeOffset,
m_LastDecryptedBlockOffset(-1)
{
aes_setkey_dec(m_AES_ctx.get(), _pVolumeKey, 128);
m_pBuffer = new u8[0x8000];
m_pBuffer = new u8[s_block_total_size];
}

bool CVolumeWiiCrypted::ChangePartition(u64 offset)
Expand All @@ -47,7 +47,6 @@ bool CVolumeWiiCrypted::ChangePartition(u64 offset)
return true;
}


CVolumeWiiCrypted::~CVolumeWiiCrypted()
{
delete[] m_pBuffer;
Expand All @@ -66,36 +65,42 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de

while (_Length > 0)
{
static unsigned char IV[16];

// math block offset
u64 Block = _ReadOffset / 0x7C00;
u64 Offset = _ReadOffset % 0x7C00;

// read current block
if (!m_pReader->Read(m_VolumeOffset + m_dataOffset + Block * 0x8000, 0x8000, m_pBuffer))
return(false);
// Calculate block offset
u64 Block = _ReadOffset / s_block_data_size;
u64 Offset = _ReadOffset % s_block_data_size;

if (m_LastDecryptedBlockOffset != Block)
{
memcpy(IV, m_pBuffer + 0x3d0, 16);
aes_crypt_cbc(m_AES_ctx.get(), AES_DECRYPT, 0x7C00, IV, m_pBuffer + 0x400, m_LastDecryptedBlock);
// Read the current block
if (!m_pReader->Read(m_VolumeOffset + m_dataOffset + Block * s_block_total_size, s_block_total_size, m_pBuffer))
return false;

// Decrypt the block's data.
// 0x3D0 - 0x3DF in m_pBuffer will be overwritten,
// but that won't affect anything, because we won't
// use the content of m_pBuffer anymore after this
aes_crypt_cbc(m_AES_ctx.get(), AES_DECRYPT, s_block_data_size, m_pBuffer + 0x3D0,
m_pBuffer + s_block_header_size, m_LastDecryptedBlock);
m_LastDecryptedBlockOffset = Block;

// The only thing we currently use from the 0x000 - 0x3FF part
// of the block is the IV (at 0x3D0), but it also contains SHA-1
// hashes that IOS uses to check that discs aren't tampered with.
// http://wiibrew.org/wiki/Wii_Disc#Encrypted
}

// copy the encrypted data
u64 MaxSizeToCopy = 0x7C00 - Offset;
// Copy the decrypted data
u64 MaxSizeToCopy = s_block_data_size - Offset;
u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length;
memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize);

// increase buffers
// Update offsets
_Length -= CopySize;
_pBuffer += CopySize;
_ReadOffset += CopySize;
}

return(true);
return true;
}

bool CVolumeWiiCrypted::GetTitleID(u8* _pBuffer) const
Expand Down
6 changes: 5 additions & 1 deletion Source/Core/DiscIO/VolumeWiiCrypted.h
Expand Up @@ -44,6 +44,10 @@ class CVolumeWiiCrypted : public IVolume
bool ChangePartition(u64 offset) override;

private:
static const unsigned int s_block_header_size = 0x0400;
static const unsigned int s_block_data_size = 0x7C00;
static const unsigned int s_block_total_size = s_block_header_size + s_block_data_size;

std::unique_ptr<IBlobReader> m_pReader;
std::unique_ptr<aes_context> m_AES_ctx;

Expand All @@ -53,7 +57,7 @@ class CVolumeWiiCrypted : public IVolume
u64 m_dataOffset;

mutable u64 m_LastDecryptedBlockOffset;
mutable unsigned char m_LastDecryptedBlock[0x8000];
mutable unsigned char m_LastDecryptedBlock[s_block_data_size];
};

} // namespace