From ef5639bfbbeb7d83bd66e3faf3e88e4aa1e05a6e Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Sat, 13 Oct 2018 08:12:00 -0400
Subject: [PATCH] key_manager: Don't assume file seeks and reads will always
 succeed

Given the filesystem should always be assumed to be volatile, we should
check and bail out if a seek operation isn't successful. This'll prevent
potentially writing/returning garbage data from the function in rare
cases.

This also allows removing a check to see if an offset is within the
bounds of a file before perfoming a seek operation. If a seek is
attempted beyond the end of a file, it will fail, so this essentially
combines two checks into one in one place.
---
 src/core/crypto/key_manager.cpp | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 4ade67d236..14d53bef9a 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -147,30 +147,38 @@ boost::optional<Key128> DeriveSDSeed() {
                                    "rb+");
     if (!save_43.IsOpen())
         return boost::none;
+
     const FileUtil::IOFile sd_private(
         FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
     if (!sd_private.IsOpen())
         return boost::none;
 
     std::array<u8, 0x10> private_seed{};
-    if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != 0x10)
+    if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
         return boost::none;
+    }
 
     std::array<u8, 0x10> buffer{};
     std::size_t offset = 0;
     for (; offset + 0x10 < save_43.GetSize(); ++offset) {
-        save_43.Seek(offset, SEEK_SET);
+        if (!save_43.Seek(offset, SEEK_SET)) {
+            return boost::none;
+        }
+
         save_43.ReadBytes(buffer.data(), buffer.size());
-        if (buffer == private_seed)
+        if (buffer == private_seed) {
             break;
+        }
     }
 
-    if (offset + 0x10 >= save_43.GetSize())
+    if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
         return boost::none;
+    }
 
     Key128 seed{};
-    save_43.Seek(offset + 0x10, SEEK_SET);
-    save_43.ReadBytes(seed.data(), seed.size());
+    if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
+        return boost::none;
+    }
     return seed;
 }
 
@@ -233,7 +241,9 @@ std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save) {
         return {};
 
     std::vector<u8> buffer(ticket_save.GetSize());
-    ticket_save.ReadBytes(buffer.data(), buffer.size());
+    if (ticket_save.ReadBytes(buffer.data(), buffer.size()) != buffer.size()) {
+        return {};
+    }
 
     std::vector<TicketRaw> out;
     u32 magic{};
-- 
GitLab