diff --git a/Source/Core/DiscIO/NANDImporter.cpp b/Source/Core/DiscIO/NANDImporter.cpp index 1772b4f6f2..220a241390 100644 --- a/Source/Core/DiscIO/NANDImporter.cpp +++ b/Source/Core/DiscIO/NANDImporter.cpp @@ -4,6 +4,7 @@ #include "DiscIO/NANDImporter.h" +#include #include #include #include @@ -15,6 +16,7 @@ #include "Common/MsgHandler.h" #include "Common/StringUtil.h" #include "Common/Swap.h" +#include "Core/IOS/ES/Formats.h" #include "DiscIO/NANDContentLoader.h" namespace DiscIO @@ -188,40 +190,73 @@ void NANDImporter::ProcessFile(const NANDFSTEntry& entry, const std::string& par } } -void NANDImporter::ExtractCertificates(const std::string& nand_root) +bool NANDImporter::ExtractCertificates(const std::string& nand_root) { - const std::string title_contents_path = - nand_root + "/title/00000001/0000000d/content/00000011.app"; - File::IOFile file(title_contents_path, "rb"); - if (!file) + const std::string content_dir = nand_root + "/title/00000001/0000000d/content/"; + + File::IOFile tmd_file(content_dir + "title.tmd", "rb"); + std::vector tmd_bytes(tmd_file.GetSize()); + if (!tmd_file.ReadBytes(tmd_bytes.data(), tmd_bytes.size())) { - PanicAlertT("Unable to open %s! Refer to " - "https://dolphin-emu.org/docs/guides/wii-network-guide/ to set up " - "certificates.", - title_contents_path.c_str()); - return; + ERROR_LOG(DISCIO, "ExtractCertificates: Could not read IOS13 TMD"); + return false; } - struct Certificate + IOS::ES::TMDReader tmd(std::move(tmd_bytes)); + IOS::ES::Content content_metadata; + if (!tmd.GetContent(tmd.GetBootIndex(), &content_metadata)) + { + ERROR_LOG(DISCIO, "ExtractCertificates: Could not get content ID from TMD"); + return false; + } + + File::IOFile content_file(content_dir + StringFromFormat("%08x.app", content_metadata.id), "rb"); + std::vector content_bytes(content_file.GetSize()); + if (!content_file.ReadBytes(content_bytes.data(), content_bytes.size())) + { + ERROR_LOG(DISCIO, "ExtractCertificates: Could not read IOS13 contents"); + return false; + } + + struct PEMCertificate { - u32 offset; - u32 size; std::string filename; + std::array search_bytes; }; - std::array certificates = {{{0x92834, 1005, "/clientca.pem"}, - {0x92d38, 609, "/clientcakey.pem"}, - {0x92440, 897, "/rootca.pem"}}}; - for (const Certificate& cert : certificates) - { - file.Seek(cert.offset, SEEK_SET); - std::vector pem_cert(cert.size); - file.ReadBytes(pem_cert.data(), pem_cert.size()); - const std::string pem_file_path = nand_root + cert.filename; + std::array certificates = {{ + {"/clientca.pem", {{0x30, 0x82, 0x03, 0xE9}}}, + {"/clientcakey.pem", {{0x30, 0x82, 0x02, 0x5D}}}, + {"/rootca.pem", {{0x30, 0x82, 0x03, 0x7D}}}, + }}; + + for (const PEMCertificate& certificate : certificates) + { + const auto search_result = + std::search(content_bytes.begin(), content_bytes.end(), certificate.search_bytes.begin(), + certificate.search_bytes.end()); + + if (search_result == content_bytes.end()) + { + ERROR_LOG(DISCIO, "ExtractCertificates: Could not find offset for certficate '%s'", + certificate.filename.c_str()); + return false; + } + + const std::string pem_file_path = nand_root + certificate.filename; + const ptrdiff_t certificate_offset = std::distance(content_bytes.begin(), search_result); + const u16 certificate_size = Common::swap16(&content_bytes[certificate_offset - 2]); + INFO_LOG(DISCIO, "ExtractCertificates: '%s' offset: 0x%tx size: 0x%x", + certificate.filename.c_str(), certificate_offset, certificate_size); + File::IOFile pem_file(pem_file_path, "wb"); - if (!pem_file.WriteBytes(pem_cert.data(), pem_cert.size())) - PanicAlertT("Unable to write to file %s", pem_file_path.c_str()); + if (!pem_file.WriteBytes(&content_bytes[certificate_offset], certificate_size)) + { + ERROR_LOG(DISCIO, "ExtractCertificates: Unable to write to file %s", pem_file_path.c_str()); + return false; + } } + return true; } void NANDImporter::ExportKeys(const std::string& nand_root) diff --git a/Source/Core/DiscIO/NANDImporter.h b/Source/Core/DiscIO/NANDImporter.h index f079c2e82d..09ed7034cb 100644 --- a/Source/Core/DiscIO/NANDImporter.h +++ b/Source/Core/DiscIO/NANDImporter.h @@ -19,7 +19,7 @@ public: ~NANDImporter(); void ImportNANDBin(const std::string& path_to_bin, std::function update_callback); - void ExtractCertificates(const std::string& nand_root); + bool ExtractCertificates(const std::string& nand_root); private: #pragma pack(push, 1)