summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/Volume.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2020-06-07 22:58:03 +0200
committerJosJuice <josjuice@gmail.com>2020-08-02 22:46:53 +0200
commita41166bb376820389d9863ce23cf6fab20cb3b5f (patch)
tree833fb8c0479af02a23f88d650838d542fa012b00 /Source/Core/DiscIO/Volume.cpp
parent25ebc3c07c6310924d662b2209f9ba5d08006ea6 (diff)
Make netplay's "same game" check more robust
Instead of comparing the game ID, revision, disc number and name, we can compare a hash of important parts of the disc including all the aforementioned data but also additional data such as the FST. The primary reason why I'm making this change is to let us catch more desyncs before they happen, but this should also fix https://bugs.dolphin-emu.org/issues/12115. As a bonus, the UI can now distinguish the case where a client doesn't have the game at all from the case where a client has the wrong version of the game.
Diffstat (limited to 'Source/Core/DiscIO/Volume.cpp')
-rw-r--r--Source/Core/DiscIO/Volume.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/Source/Core/DiscIO/Volume.cpp b/Source/Core/DiscIO/Volume.cpp
index 23df2afc5c..ab4b0e562b 100644
--- a/Source/Core/DiscIO/Volume.cpp
+++ b/Source/Core/DiscIO/Volume.cpp
@@ -9,12 +9,16 @@
#include <memory>
#include <optional>
#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
+#include <mbedtls/sha1.h>
+
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
+#include "Core/IOS/ES/Formats.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/VolumeDisc.h"
@@ -28,6 +32,43 @@ const IOS::ES::TicketReader Volume::INVALID_TICKET{};
const IOS::ES::TMDReader Volume::INVALID_TMD{};
const std::vector<u8> Volume::INVALID_CERT_CHAIN{};
+template <typename T>
+static void AddToSyncHash(mbedtls_sha1_context* context, const T& data)
+{
+ static_assert(std::is_trivially_copyable_v<T>);
+ mbedtls_sha1_update_ret(context, reinterpret_cast<const u8*>(&data), sizeof(data));
+}
+
+void Volume::ReadAndAddToSyncHash(mbedtls_sha1_context* context, u64 offset, u64 length,
+ const Partition& partition) const
+{
+ std::vector<u8> buffer(length);
+ if (Read(offset, length, buffer.data(), partition))
+ mbedtls_sha1_update_ret(context, buffer.data(), buffer.size());
+}
+
+void Volume::AddTMDToSyncHash(mbedtls_sha1_context* context, const Partition& partition) const
+{
+ // We want to hash some important parts of the TMD, but nothing that changes when fakesigning.
+ // (Fakesigned WADs are very popular, and we don't want people with properly signed WADs to
+ // unnecessarily be at a disadvantage due to most netplay partners having fakesigned WADs.)
+
+ const IOS::ES::TMDReader& tmd = GetTMD(partition);
+ if (!tmd.IsValid())
+ return;
+
+ AddToSyncHash(context, tmd.GetIOSId());
+ AddToSyncHash(context, tmd.GetTitleId());
+ AddToSyncHash(context, tmd.GetTitleFlags());
+ AddToSyncHash(context, tmd.GetGroupId());
+ AddToSyncHash(context, tmd.GetRegion());
+ AddToSyncHash(context, tmd.GetTitleVersion());
+ AddToSyncHash(context, tmd.GetBootIndex());
+
+ for (const IOS::ES::Content& content : tmd.GetContents())
+ AddToSyncHash(context, content);
+}
+
std::map<Language, std::string> Volume::ReadWiiNames(const std::vector<char16_t>& data)
{
std::map<Language, std::string> names;