diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index b2a0e0e802..7255c79107 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -81,6 +81,12 @@ public: s32 ipc_fd = -1; }; + enum class CheckContentHashes : bool + { + Yes = true, + No = false, + }; + IOS::ES::TMDReader FindImportTMD(u64 title_id) const; IOS::ES::TMDReader FindInstalledTMD(u64 title_id) const; IOS::ES::TicketReader FindSignedTicket(u64 title_id) const; @@ -92,7 +98,9 @@ public: // Get titles for which there is a ticket (in /ticket). std::vector GetTitlesWithTickets() const; - std::vector GetStoredContentsFromTMD(const IOS::ES::TMDReader& tmd) const; + std::vector + GetStoredContentsFromTMD(const IOS::ES::TMDReader& tmd, + CheckContentHashes check_content_hashes = CheckContentHashes::No) const; u32 GetSharedContentsCount() const; std::vector> GetSharedContents() const; diff --git a/Source/Core/Core/IOS/ES/NandUtils.cpp b/Source/Core/Core/IOS/ES/NandUtils.cpp index 6ff03bb89e..af35bc4d9a 100644 --- a/Source/Core/Core/IOS/ES/NandUtils.cpp +++ b/Source/Core/Core/IOS/ES/NandUtils.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" @@ -163,7 +164,9 @@ std::vector ES::GetTitlesWithTickets() const return title_ids; } -std::vector ES::GetStoredContentsFromTMD(const IOS::ES::TMDReader& tmd) const +std::vector +ES::GetStoredContentsFromTMD(const IOS::ES::TMDReader& tmd, + CheckContentHashes check_content_hashes) const { if (!tmd.IsValid()) return {}; @@ -174,10 +177,29 @@ std::vector ES::GetStoredContentsFromTMD(const IOS::ES::TMDRea std::vector stored_contents; std::copy_if(contents.begin(), contents.end(), std::back_inserter(stored_contents), - [this, &tmd, &map](const IOS::ES::Content& content) { + [this, &tmd, &map, check_content_hashes](const IOS::ES::Content& content) { + const auto fs = m_ios.GetFS(); + const std::string path = GetContentPath(tmd.GetTitleId(), content, map); - return !path.empty() && - m_ios.GetFS()->GetMetadata(PID_KERNEL, PID_KERNEL, path).Succeeded(); + if (path.empty()) + return false; + + // Check whether the content file exists. + const auto file = fs->OpenFile(PID_KERNEL, PID_KERNEL, path, FS::Mode::Read); + if (!file.Succeeded()) + return false; + + // If content hash checks are disabled, all we have to do is check for existence. + if (check_content_hashes == CheckContentHashes::No) + return true; + + // Otherwise, check whether the installed content SHA1 matches the expected hash. + std::vector content_data(file->GetStatus()->size); + if (!file->Read(content_data.data(), content_data.size())) + return false; + std::array sha1{}; + mbedtls_sha1_ret(content_data.data(), content_data.size(), sha1.data()); + return sha1 == content.sha1; }); return stored_contents; diff --git a/Source/Core/Core/IOS/FS/FileSystem.h b/Source/Core/Core/IOS/FS/FileSystem.h index 7d53b6ca0f..24274b7528 100644 --- a/Source/Core/Core/IOS/FS/FileSystem.h +++ b/Source/Core/Core/IOS/FS/FileSystem.h @@ -205,6 +205,7 @@ public: /// Reposition the file offset for a file descriptor. virtual Result SeekFile(Fd fd, u32 offset, SeekMode mode) = 0; /// Get status for a file descriptor. + /// Guaranteed to succeed for a valid file descriptor. virtual Result GetFileStatus(Fd fd) = 0; /// Create a file with the specified path and metadata. diff --git a/Source/Core/Core/WiiUtils.cpp b/Source/Core/Core/WiiUtils.cpp index d0d0395efb..0abc8de162 100644 --- a/Source/Core/Core/WiiUtils.cpp +++ b/Source/Core/Core/WiiUtils.cpp @@ -149,7 +149,8 @@ bool InstallWAD(IOS::HLE::Kernel& ios, const DiscIO::VolumeWAD& wad, InstallType const u64 title_id = wad.GetTMD().GetTitleId(); // Skip the install if the WAD is already installed. - const auto installed_contents = ios.GetES()->GetStoredContentsFromTMD(wad.GetTMD()); + const auto installed_contents = ios.GetES()->GetStoredContentsFromTMD( + wad.GetTMD(), IOS::HLE::Device::ES::CheckContentHashes::Yes); if (wad.GetTMD().GetContents() == installed_contents) { // Clear the "temporary title ID" flag in case the user tries to permanently install a title