diff options
| author | Markus Wick <degasus@users.noreply.github.com> | 2020-04-24 15:01:04 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-24 15:01:04 +0200 |
| commit | 0a71dda8a0c615e8f387dc12d519cf3415a5ef79 (patch) | |
| tree | d988a05e13e5cf27800a43392aa96718bbae2e87 /Source/Core/DiscIO/WiiEncryptionCache.cpp | |
| parent | 7e94d6ed375cecae59717626f6ab1b32674a15dc (diff) | |
| parent | 432f342bc86fe43ffbecfd6657d2331e79e47ffc (diff) | |
Merge pull request #8591 from JosJuice/wii-reencryption
DiscIO: Implement re-encryption of Wii partition data
Diffstat (limited to 'Source/Core/DiscIO/WiiEncryptionCache.cpp')
| -rw-r--r-- | Source/Core/DiscIO/WiiEncryptionCache.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/Source/Core/DiscIO/WiiEncryptionCache.cpp b/Source/Core/DiscIO/WiiEncryptionCache.cpp new file mode 100644 index 0000000000..c5a2111daa --- /dev/null +++ b/Source/Core/DiscIO/WiiEncryptionCache.cpp @@ -0,0 +1,80 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DiscIO/WiiEncryptionCache.h" + +#include <array> +#include <cstring> +#include <limits> +#include <memory> + +#include "Common/Align.h" +#include "Common/CommonTypes.h" +#include "DiscIO/Blob.h" +#include "DiscIO/VolumeWii.h" + +namespace DiscIO +{ +WiiEncryptionCache::WiiEncryptionCache(BlobReader* blob) : m_blob(blob) +{ +} + +WiiEncryptionCache::~WiiEncryptionCache() = default; + +const std::array<u8, VolumeWii::GROUP_TOTAL_SIZE>* +WiiEncryptionCache::EncryptGroup(u64 offset, u64 partition_data_offset, + u64 partition_data_decrypted_size, const Key& key) +{ + // Only allocate memory if this function actually ends up getting called + if (!m_cache) + { + m_cache = std::make_unique<std::array<u8, VolumeWii::GROUP_TOTAL_SIZE>>(); + ASSERT(m_blob->SupportsReadWiiDecrypted()); + } + + ASSERT(offset % VolumeWii::GROUP_TOTAL_SIZE == 0); + const u64 group_offset_in_partition = + offset / VolumeWii::GROUP_TOTAL_SIZE * VolumeWii::GROUP_DATA_SIZE; + const u64 group_offset_on_disc = partition_data_offset + offset; + + if (m_cached_offset != group_offset_on_disc) + { + if (!VolumeWii::EncryptGroup(group_offset_in_partition, partition_data_offset, + partition_data_decrypted_size, key, m_blob, m_cache.get())) + { + m_cached_offset = std::numeric_limits<u64>::max(); // Invalidate the cache + return nullptr; + } + + m_cached_offset = group_offset_on_disc; + } + + return m_cache.get(); +} + +bool WiiEncryptionCache::EncryptGroups(u64 offset, u64 size, u8* out_ptr, u64 partition_data_offset, + u64 partition_data_decrypted_size, const Key& key) +{ + while (size > 0) + { + const std::array<u8, VolumeWii::GROUP_TOTAL_SIZE>* group = + EncryptGroup(Common::AlignDown(offset, VolumeWii::GROUP_TOTAL_SIZE), partition_data_offset, + partition_data_decrypted_size, key); + + if (!group) + return false; + + const u64 offset_in_group = offset % VolumeWii::GROUP_TOTAL_SIZE; + const u64 bytes_to_read = std::min(VolumeWii::GROUP_TOTAL_SIZE - offset_in_group, size); + std::memcpy(out_ptr, group->data() + offset_in_group, bytes_to_read); + + offset += bytes_to_read; + size -= bytes_to_read; + out_ptr += bytes_to_read; + } + + return true; +} + +} // namespace DiscIO |
