diff options
| author | 2020-11-29 10:54:09 -0500 | |
|---|---|---|
| committer | 2020-12-18 10:33:28 -0500 | |
| commit | d46ca5a0157a5267b4c2ebf0515f1a492434071a (patch) | |
| tree | a10347483315f757056382b4d552098d32c4e9f8 /src | |
| parent | ns_vm: Stub NeedsUpdateVulnerability (diff) | |
| download | yuzu-d46ca5a0157a5267b4c2ebf0515f1a492434071a.tar.gz yuzu-d46ca5a0157a5267b4c2ebf0515f1a492434071a.tar.xz yuzu-d46ca5a0157a5267b4c2ebf0515f1a492434071a.zip | |
pl_u, applets/web: Decrypt shared fonts to TTF files
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/am/applets/web_browser.cpp | 86 | ||||
| -rw-r--r-- | src/core/hle/service/ns/pl_u.cpp | 30 | ||||
| -rw-r--r-- | src/core/hle/service/ns/pl_u.h | 19 |
3 files changed, 117 insertions, 18 deletions
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index c0c98ad30..02ce9f387 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -16,12 +16,14 @@ | |||
| 16 | #include "core/file_sys/romfs.h" | 16 | #include "core/file_sys/romfs.h" |
| 17 | #include "core/file_sys/system_archive/system_archive.h" | 17 | #include "core/file_sys/system_archive/system_archive.h" |
| 18 | #include "core/file_sys/vfs_types.h" | 18 | #include "core/file_sys/vfs_types.h" |
| 19 | #include "core/file_sys/vfs_vector.h" | ||
| 19 | #include "core/frontend/applets/web_browser.h" | 20 | #include "core/frontend/applets/web_browser.h" |
| 20 | #include "core/hle/kernel/process.h" | 21 | #include "core/hle/kernel/process.h" |
| 21 | #include "core/hle/result.h" | 22 | #include "core/hle/result.h" |
| 22 | #include "core/hle/service/am/am.h" | 23 | #include "core/hle/service/am/am.h" |
| 23 | #include "core/hle/service/am/applets/web_browser.h" | 24 | #include "core/hle/service/am/applets/web_browser.h" |
| 24 | #include "core/hle/service/filesystem/filesystem.h" | 25 | #include "core/hle/service/filesystem/filesystem.h" |
| 26 | #include "core/hle/service/ns/pl_u.h" | ||
| 25 | 27 | ||
| 26 | namespace Service::AM::Applets { | 28 | namespace Service::AM::Applets { |
| 27 | 29 | ||
| @@ -123,6 +125,88 @@ FileSys::VirtualFile GetOfflineRomFS(Core::System& system, u64 title_id, | |||
| 123 | } | 125 | } |
| 124 | } | 126 | } |
| 125 | 127 | ||
| 128 | void ExtractSharedFonts(Core::System& system) { | ||
| 129 | static constexpr std::array<const char*, 7> DECRYPTED_SHARED_FONTS{ | ||
| 130 | "FontStandard.ttf", | ||
| 131 | "FontChineseSimplified.ttf", | ||
| 132 | "FontExtendedChineseSimplified.ttf", | ||
| 133 | "FontChineseTraditional.ttf", | ||
| 134 | "FontKorean.ttf", | ||
| 135 | "FontNintendoExtended.ttf", | ||
| 136 | "FontNintendoExtended2.ttf", | ||
| 137 | }; | ||
| 138 | |||
| 139 | for (std::size_t i = 0; i < NS::SHARED_FONTS.size(); ++i) { | ||
| 140 | const auto fonts_dir = Common::FS::SanitizePath( | ||
| 141 | fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)), | ||
| 142 | Common::FS::DirectorySeparator::PlatformDefault); | ||
| 143 | |||
| 144 | const auto font_file_path = | ||
| 145 | Common::FS::SanitizePath(fmt::format("{}/{}", fonts_dir, DECRYPTED_SHARED_FONTS[i]), | ||
| 146 | Common::FS::DirectorySeparator::PlatformDefault); | ||
| 147 | |||
| 148 | if (Common::FS::Exists(font_file_path)) { | ||
| 149 | continue; | ||
| 150 | } | ||
| 151 | |||
| 152 | const auto font = NS::SHARED_FONTS[i]; | ||
| 153 | const auto font_title_id = static_cast<u64>(font.first); | ||
| 154 | |||
| 155 | const auto nca = system.GetFileSystemController().GetSystemNANDContents()->GetEntry( | ||
| 156 | font_title_id, FileSys::ContentRecordType::Data); | ||
| 157 | |||
| 158 | FileSys::VirtualFile romfs; | ||
| 159 | |||
| 160 | if (!nca) { | ||
| 161 | romfs = FileSys::SystemArchive::SynthesizeSystemArchive(font_title_id); | ||
| 162 | } else { | ||
| 163 | romfs = nca->GetRomFS(); | ||
| 164 | } | ||
| 165 | |||
| 166 | if (!romfs) { | ||
| 167 | LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} cannot be extracted!", | ||
| 168 | font_title_id); | ||
| 169 | continue; | ||
| 170 | } | ||
| 171 | |||
| 172 | const auto extracted_romfs = FileSys::ExtractRomFS(romfs); | ||
| 173 | |||
| 174 | if (!extracted_romfs) { | ||
| 175 | LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} failed to extract!", | ||
| 176 | font_title_id); | ||
| 177 | continue; | ||
| 178 | } | ||
| 179 | |||
| 180 | const auto font_file = extracted_romfs->GetFile(font.second); | ||
| 181 | |||
| 182 | if (!font_file) { | ||
| 183 | LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} has no font file \"{}\"!", | ||
| 184 | font_title_id, font.second); | ||
| 185 | continue; | ||
| 186 | } | ||
| 187 | |||
| 188 | std::vector<u32> font_data_u32(font_file->GetSize() / sizeof(u32)); | ||
| 189 | font_file->ReadBytes<u32>(font_data_u32.data(), font_file->GetSize()); | ||
| 190 | |||
| 191 | std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(), | ||
| 192 | Common::swap32); | ||
| 193 | |||
| 194 | std::vector<u8> decrypted_data(font_file->GetSize() - 8); | ||
| 195 | |||
| 196 | NS::DecryptSharedFontToTTF(font_data_u32, decrypted_data); | ||
| 197 | |||
| 198 | FileSys::VirtualFile decrypted_font = std::make_shared<FileSys::VectorVfsFile>( | ||
| 199 | std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]); | ||
| 200 | |||
| 201 | const auto temp_dir = | ||
| 202 | system.GetFilesystem()->CreateDirectory(fonts_dir, FileSys::Mode::ReadWrite); | ||
| 203 | |||
| 204 | const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]); | ||
| 205 | |||
| 206 | FileSys::VfsRawCopy(decrypted_font, out_file); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 126 | } // namespace | 210 | } // namespace |
| 127 | 211 | ||
| 128 | WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) | 212 | WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_) |
| @@ -155,6 +239,8 @@ void WebBrowser::Initialize() { | |||
| 155 | LOG_DEBUG(Service_AM, "WebArgHeader: total_tlv_entries={}, shim_kind={}", | 239 | LOG_DEBUG(Service_AM, "WebArgHeader: total_tlv_entries={}, shim_kind={}", |
| 156 | web_arg_header.total_tlv_entries, web_arg_header.shim_kind); | 240 | web_arg_header.total_tlv_entries, web_arg_header.shim_kind); |
| 157 | 241 | ||
| 242 | ExtractSharedFonts(system); | ||
| 243 | |||
| 158 | switch (web_arg_header.shim_kind) { | 244 | switch (web_arg_header.shim_kind) { |
| 159 | case ShimKind::Shop: | 245 | case ShimKind::Shop: |
| 160 | InitializeShop(); | 246 | InitializeShop(); |
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index c8a215845..71c7587db 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp | |||
| @@ -27,29 +27,11 @@ | |||
| 27 | 27 | ||
| 28 | namespace Service::NS { | 28 | namespace Service::NS { |
| 29 | 29 | ||
| 30 | enum class FontArchives : u64 { | ||
| 31 | Extension = 0x0100000000000810, | ||
| 32 | Standard = 0x0100000000000811, | ||
| 33 | Korean = 0x0100000000000812, | ||
| 34 | ChineseTraditional = 0x0100000000000813, | ||
| 35 | ChineseSimple = 0x0100000000000814, | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct FontRegion { | 30 | struct FontRegion { |
| 39 | u32 offset; | 31 | u32 offset; |
| 40 | u32 size; | 32 | u32 size; |
| 41 | }; | 33 | }; |
| 42 | 34 | ||
| 43 | constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{ | ||
| 44 | std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"), | ||
| 45 | std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"), | ||
| 46 | std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"), | ||
| 47 | std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"), | ||
| 48 | std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"), | ||
| 49 | std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"), | ||
| 50 | std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"), | ||
| 51 | }; | ||
| 52 | |||
| 53 | // The below data is specific to shared font data dumped from Switch on f/w 2.2 | 35 | // The below data is specific to shared font data dumped from Switch on f/w 2.2 |
| 54 | // Virtual address and offsets/sizes likely will vary by dump | 36 | // Virtual address and offsets/sizes likely will vary by dump |
| 55 | [[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL}; | 37 | [[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL}; |
| @@ -80,6 +62,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem | |||
| 80 | offset += transformed_font.size() * sizeof(u32); | 62 | offset += transformed_font.size() * sizeof(u32); |
| 81 | } | 63 | } |
| 82 | 64 | ||
| 65 | void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { | ||
| 66 | ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); | ||
| 67 | |||
| 68 | const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor | ||
| 69 | std::vector<u32> transformed_font(input.size()); | ||
| 70 | // TODO(ogniK): Figure out a better way to do this | ||
| 71 | std::transform(input.begin(), input.end(), transformed_font.begin(), | ||
| 72 | [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); | ||
| 73 | transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size | ||
| 74 | std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32)); | ||
| 75 | } | ||
| 76 | |||
| 83 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, | 77 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, |
| 84 | std::size_t& offset) { | 78 | std::size_t& offset) { |
| 85 | ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, | 79 | ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE, |
diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h index 224dcb997..f920c7f69 100644 --- a/src/core/hle/service/ns/pl_u.h +++ b/src/core/hle/service/ns/pl_u.h | |||
| @@ -16,6 +16,25 @@ class FileSystemController; | |||
| 16 | 16 | ||
| 17 | namespace NS { | 17 | namespace NS { |
| 18 | 18 | ||
| 19 | enum class FontArchives : u64 { | ||
| 20 | Extension = 0x0100000000000810, | ||
| 21 | Standard = 0x0100000000000811, | ||
| 22 | Korean = 0x0100000000000812, | ||
| 23 | ChineseTraditional = 0x0100000000000813, | ||
| 24 | ChineseSimple = 0x0100000000000814, | ||
| 25 | }; | ||
| 26 | |||
| 27 | constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{ | ||
| 28 | std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"), | ||
| 29 | std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"), | ||
| 30 | std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"), | ||
| 31 | std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"), | ||
| 32 | std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"), | ||
| 33 | std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"), | ||
| 34 | std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"), | ||
| 35 | }; | ||
| 36 | |||
| 37 | void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output); | ||
| 19 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); | 38 | void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset); |
| 20 | 39 | ||
| 21 | class PL_U final : public ServiceFramework<PL_U> { | 40 | class PL_U final : public ServiceFramework<PL_U> { |