summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/WiiEncryptionCache.cpp
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2020-04-24 15:01:04 +0200
committerGitHub <noreply@github.com>2020-04-24 15:01:04 +0200
commit0a71dda8a0c615e8f387dc12d519cf3415a5ef79 (patch)
treed988a05e13e5cf27800a43392aa96718bbae2e87 /Source/Core/DiscIO/WiiEncryptionCache.cpp
parent7e94d6ed375cecae59717626f6ab1b32674a15dc (diff)
parent432f342bc86fe43ffbecfd6657d2331e79e47ffc (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.cpp80
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