From 319c50897881c7ee1aba8e0bfe396cb385d9eb37 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Thu, 23 Jan 2020 16:47:49 +0100 Subject: DiscIO: Implement re-encryption of Wii partition data --- Source/Core/DiscIO/WiiEncryptionCache.cpp | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Source/Core/DiscIO/WiiEncryptionCache.cpp (limited to 'Source/Core/DiscIO/WiiEncryptionCache.cpp') 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 +#include +#include +#include + +#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* +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>(); + 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::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* 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 -- cgit v1.2.3