From 521ccd7b44f08054beac77a0abcc7812ae6b590b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Mon, 26 Jan 2015 15:59:25 +0100 Subject: [PATCH 1/2] VolumeWiiCrypted: Decryption optimization The block doesn't have to be read if it already is in m_pBuffer. --- Source/Core/DiscIO/VolumeWiiCrypted.cpp | 30 ++++++++++++++----------- Source/Core/DiscIO/VolumeWiiCrypted.h | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index d956b9444d..57545eee01 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -47,7 +47,6 @@ bool CVolumeWiiCrypted::ChangePartition(u64 offset) return true; } - CVolumeWiiCrypted::~CVolumeWiiCrypted() { delete[] m_pBuffer; @@ -66,36 +65,41 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de while (_Length > 0) { - static unsigned char IV[16]; - - // math block offset + // Calculate 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); - 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 * 0x8000, 0x8000, 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, 0x7C00, m_pBuffer + 0x3D0, m_pBuffer + 0x400, 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 + // Copy the decrypted data u64 MaxSizeToCopy = 0x7C00 - 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 diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index 1cca81c410..608964dc64 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -53,7 +53,7 @@ private: u64 m_dataOffset; mutable u64 m_LastDecryptedBlockOffset; - mutable unsigned char m_LastDecryptedBlock[0x8000]; + mutable unsigned char m_LastDecryptedBlock[0x7C00]; }; } // namespace From 28b441ebea81e847e720f8322eb8668e33e996ae Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Feb 2015 10:31:17 +0100 Subject: [PATCH 2/2] VolumeWiiCrypted: Replace some hardcoded values with constants --- Source/Core/DiscIO/VolumeWiiCrypted.cpp | 13 +++++++------ Source/Core/DiscIO/VolumeWiiCrypted.h | 6 +++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index 57545eee01..dad2977ba0 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -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) @@ -66,20 +66,21 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de while (_Length > 0) { // Calculate block offset - u64 Block = _ReadOffset / 0x7C00; - u64 Offset = _ReadOffset % 0x7C00; + u64 Block = _ReadOffset / s_block_data_size; + u64 Offset = _ReadOffset % s_block_data_size; if (m_LastDecryptedBlockOffset != Block) { // Read the current block - if (!m_pReader->Read(m_VolumeOffset + m_dataOffset + Block * 0x8000, 0x8000, m_pBuffer)) + 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, 0x7C00, m_pBuffer + 0x3D0, m_pBuffer + 0x400, m_LastDecryptedBlock); + 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 @@ -89,7 +90,7 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de } // Copy the decrypted data - u64 MaxSizeToCopy = 0x7C00 - Offset; + u64 MaxSizeToCopy = s_block_data_size - Offset; u64 CopySize = (_Length > MaxSizeToCopy) ? MaxSizeToCopy : _Length; memcpy(_pBuffer, &m_LastDecryptedBlock[Offset], (size_t)CopySize); diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index 608964dc64..5e5e1e196d 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -44,6 +44,10 @@ public: 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 m_pReader; std::unique_ptr m_AES_ctx; @@ -53,7 +57,7 @@ private: u64 m_dataOffset; mutable u64 m_LastDecryptedBlockOffset; - mutable unsigned char m_LastDecryptedBlock[0x7C00]; + mutable unsigned char m_LastDecryptedBlock[s_block_data_size]; }; } // namespace