mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #5130 from B3n30/warn_if_cia_contend_is_encrypted
Show an error if CIA contend is encrypted
This commit is contained in:
		
						commit
						026a63bcf7
					
				
					 5 changed files with 77 additions and 5 deletions
				
			
		|  | @ -46,13 +46,15 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign | |||
|         const bool is_dir = FileUtil::IsDirectory(physical_name); | ||||
|         if (!is_dir && HasSupportedFileExtension(physical_name)) { | ||||
|             std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name); | ||||
|             if (!loader) | ||||
|             if (!loader) { | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             bool executable = false; | ||||
|             loader->IsExecutable(executable); | ||||
|             if (!executable) | ||||
|             const auto res = loader->IsExecutable(executable); | ||||
|             if (!executable && res != Loader::ResultStatus::ErrorEncrypted) { | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             u64 program_id = 0; | ||||
|             loader->ReadProgramId(program_id); | ||||
|  |  | |||
|  | @ -133,8 +133,39 @@ Loader::ResultStatus NCCHContainer::OpenFile(const std::string& filepath, u32 nc | |||
|     return Loader::ResultStatus::Success; | ||||
| } | ||||
| 
 | ||||
| Loader::ResultStatus NCCHContainer::LoadHeader() { | ||||
|     if (has_header) { | ||||
|         return Loader::ResultStatus::Success; | ||||
|     } | ||||
|     if (!file.IsOpen()) { | ||||
|         return Loader::ResultStatus::Error; | ||||
|     } | ||||
| 
 | ||||
|     // Reset read pointer in case this file has been read before.
 | ||||
|     file.Seek(ncch_offset, SEEK_SET); | ||||
| 
 | ||||
|     if (file.ReadBytes(&ncch_header, sizeof(NCCH_Header)) != sizeof(NCCH_Header)) { | ||||
|         return Loader::ResultStatus::Error; | ||||
|     } | ||||
| 
 | ||||
|     // Skip NCSD header and load first NCCH (NCSD is just a container of NCCH files)...
 | ||||
|     if (Loader::MakeMagic('N', 'C', 'S', 'D') == ncch_header.magic) { | ||||
|         LOG_DEBUG(Service_FS, "Only loading the first (bootable) NCCH within the NCSD file!"); | ||||
|         ncch_offset += 0x4000; | ||||
|         file.Seek(ncch_offset, SEEK_SET); | ||||
|         file.ReadBytes(&ncch_header, sizeof(NCCH_Header)); | ||||
|     } | ||||
| 
 | ||||
|     // Verify we are loading the correct file type...
 | ||||
|     if (Loader::MakeMagic('N', 'C', 'C', 'H') != ncch_header.magic) { | ||||
|         return Loader::ResultStatus::ErrorInvalidFormat; | ||||
|     } | ||||
| 
 | ||||
|     has_header = true; | ||||
|     return Loader::ResultStatus::Success; | ||||
| } | ||||
| 
 | ||||
| Loader::ResultStatus NCCHContainer::Load() { | ||||
|     LOG_INFO(Service_FS, "Loading NCCH from file {}", filepath); | ||||
|     if (is_loaded) | ||||
|         return Loader::ResultStatus::Success; | ||||
| 
 | ||||
|  | @ -697,7 +728,7 @@ Loader::ResultStatus NCCHContainer::ReadOverrideRomFS(std::shared_ptr<RomFSReade | |||
| } | ||||
| 
 | ||||
| Loader::ResultStatus NCCHContainer::ReadProgramId(u64_le& program_id) { | ||||
|     Loader::ResultStatus result = Load(); | ||||
|     Loader::ResultStatus result = LoadHeader(); | ||||
|     if (result != Loader::ResultStatus::Success) | ||||
|         return result; | ||||
| 
 | ||||
|  |  | |||
|  | @ -210,6 +210,12 @@ public: | |||
| 
 | ||||
|     Loader::ResultStatus OpenFile(const std::string& filepath, u32 ncch_offset = 0); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Ensure NCCH header is loaded and ready for reading sections | ||||
|      * @return ResultStatus result of function | ||||
|      */ | ||||
|     Loader::ResultStatus LoadHeader(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Ensure ExeFS and exheader is loaded and ready for reading sections | ||||
|      * @return ResultStatus result of function | ||||
|  |  | |||
|  | @ -47,6 +47,7 @@ std::optional<std::array<u8, 16>> Ticket::GetTitleKey() const { | |||
|     std::memcpy(ctr.data(), &ticket_body.title_id, sizeof(u64)); | ||||
|     HW::AES::SelectCommonKeyIndex(ticket_body.common_key_index); | ||||
|     if (!HW::AES::IsNormalKeyAvailable(HW::AES::KeySlotID::TicketCommonKey)) { | ||||
|         LOG_ERROR(Service_FS, "CommonKey {} missing", ticket_body.common_key_index); | ||||
|         return {}; | ||||
|     } | ||||
|     auto key = HW::AES::GetNormalKey(HW::AES::KeySlotID::TicketCommonKey); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <cryptopp/aes.h> | ||||
| #include <cryptopp/modes.h> | ||||
| #include <fmt/format.h> | ||||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/string_util.h" | ||||
|  | @ -373,6 +374,37 @@ InstallStatus InstallCIA(const std::string& path, | |||
|         installFile.Close(); | ||||
| 
 | ||||
|         LOG_INFO(Service_AM, "Installed {} successfully.", path); | ||||
| 
 | ||||
|         const FileUtil::DirectoryEntryCallable callback = | ||||
|             [&callback](u64* num_entries_out, const std::string& directory, | ||||
|                         const std::string& virtual_name) -> bool { | ||||
|             const std::string physical_name = directory + DIR_SEP + virtual_name; | ||||
|             const bool is_dir = FileUtil::IsDirectory(physical_name); | ||||
|             if (!is_dir) { | ||||
|                 std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name); | ||||
|                 if (!loader) { | ||||
|                     return true; | ||||
|                 } | ||||
| 
 | ||||
|                 bool executable = false; | ||||
|                 const auto res = loader->IsExecutable(executable); | ||||
|                 if (res == Loader::ResultStatus::ErrorEncrypted) { | ||||
|                     return false; | ||||
|                 } | ||||
|                 return true; | ||||
|             } else { | ||||
|                 return FileUtil::ForeachDirectoryEntry(nullptr, physical_name, callback); | ||||
|             } | ||||
|         }; | ||||
|         if (!FileUtil::ForeachDirectoryEntry( | ||||
|                 nullptr, | ||||
|                 GetTitlePath( | ||||
|                     Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID()), | ||||
|                     container.GetTitleMetadata().GetTitleID()), | ||||
|                 callback)) { | ||||
|             LOG_ERROR(Service_AM, "CIA {} contained encrypted files.", path); | ||||
|             return InstallStatus::ErrorEncrypted; | ||||
|         } | ||||
|         return InstallStatus::Success; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue